zammbi
|
 |
«
Posted
2009-04-02 10:34:28 » |
|
Been learning JavaFX, but still can't get my head around nodes, in how to use them correctly for my game. I'm looking into creating a basic game which will use 32x32 tiles, with gravity and collision. I guess sorta like Virus effect Anyone can help me to get started? I have looked around JavaFX site, google, etc but nothing I can really find that does such an example...
|
|
|
|
|
|
zammbi
|
 |
«
Reply #2 - Posted
2009-04-03 02:16:43 » |
|
Indeed I looked at the samples. I looked at that a few times. It really didn't help my case. Well I have found something on the tiles: http://silveiraneto.net/2009/01/06/javafx-easy-use-of-tiles/I have basic gravity working now, and I think I know how to do collision so I'll play around and see what I come up with...
|
|
|
|
Games published by our own members! Check 'em out!
|
|
|
|
zammbi
|
 |
«
Reply #4 - Posted
2009-04-03 05:26:01 » |
|
Yeah I had seen that game before. But thanks.
|
|
|
|
aNt
|
 |
«
Reply #5 - Posted
2009-04-03 12:39:41 » |
|
zamm how far have you got in javafx? i take it you can make a stage, scene and groupnode (up to drawing stuff). are you getting stuff to move around? have work out loading images and interaction?
hard to guess where to start.
|
|
|
|
|
zammbi
|
 |
«
Reply #6 - Posted
2009-04-03 13:25:27 » |
|
Well I can basically show what I've done: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
| var upkey = false; var rightkey = false; var downkey = false; var leftkey = false; var leftMouse = false; var rightMouse = false; var bullet: Bullet[];
var gamelogics = Timeline { repeatCount: Timeline.INDEFINITE keyFrames: KeyFrame { time: 1ms action: function() { if((robot.translateY + robot.height) < 450){ robot.translateY+=.4; } if(upkey){ robot.translateY-=.5; } else if(downkey){ robot.translateY-=.4; } if(rightkey){ robot.translateX += .2; } else if(leftkey){ robot.translateX -= .2; } for(b in bullet){ if(b.translateX > 5000){ delete b from bullet; } else b.translateX+= 1; } } } }
def robot = new Robot;
public class RenderWindow extends Scene{
init{ this.content = [ Group{ onKeyPressed: function(e:KeyEvent){ if (e.code == KeyCode.VK_DOWN) { downkey = true; } else if (e.code == KeyCode.VK_UP) { upkey = true; }else if (e.code == KeyCode.VK_LEFT) { leftkey = true; }else if (e.code == KeyCode.VK_RIGHT) { rightkey = true; } } onKeyReleased: function(e: KeyEvent){ if (e.code == KeyCode.VK_DOWN) { downkey = false; } else if (e.code == KeyCode.VK_UP) { upkey = false; }else if (e.code == KeyCode.VK_LEFT) { leftkey = false; }else if (e.code == KeyCode.VK_RIGHT) { rightkey = false; } } onMousePressed: function(e:MouseEvent){ if(e.button == MouseButton.PRIMARY){ leftMouse = true; } if(e.button == MouseButton.SECONDARY){ rightMouse = true; } }; onMouseReleased: function(e:MouseEvent){ if(e.button == MouseButton.PRIMARY){ leftMouse = false; var b = Bullet{ translateY : robot.translateY; translateX : robot.translateX; }; insert b into bullet; } if(e.button == MouseButton.SECONDARY){ rightMouse = false; } }; content: bind[ Rectangle { x: 0, y: 0, width: 500, height: 500, fill: Color.LIGHTGRAY }, robot bullet ] } ]; gamelogics.play(); } } public class Robot extends CustomNode{
public-read var width = 30; public-read var height = 30;
override function create():Node{
Rectangle { x: 0, y: 0, width: 30, height: 30, fill: Color.STEELBLUE cache: true }; }; } public class Bullet extends CustomNode{
var r = Random{}; override function create():Node{ Group{ content: [ Line { var temp = r.nextInt(10); startX: r.nextInt(10) startY: temp endX: r.nextInt(100) endY: temp strokeWidth: 1 stroke: Color.SLATEGRAY } ] effect: MotionBlur { angle: 10 radius: 20 } cache: true } } } Stage { title: "Robot Game" width: 500 height: 500 scene: RenderWindow{} }
|
Just working around with the basics first. If you have any tips to improve this or point out what I've done wrong, that would be great. Seems to lag a little when I fire a lot of bullets, and its not the motion blur that's causing it.
|
|
|
|
elix
Senior Newbie 
|
 |
«
Reply #7 - Posted
2009-04-04 07:05:40 » |
|
I didn't notice any lag, is my pc too strong  ? I would say effects could slow down but you already said that it isn't the case. Try to set "canSkip" parameter of KeyFrame to true.
|
|
|
|
|
zammbi
|
 |
«
Reply #8 - Posted
2009-04-04 07:31:17 » |
|
Well my laptop is new and a fairly good one. After about 20 constant clicks it just major lags for me. It seems to draw off screen? But even then I still want to have 20 bullets on screen, when I add bots and what not.
Skip slows everything down, I guess it skips both frames and logic in my case, which is not what I want.
But onto better news I have collision working, bullets now can destroy objects(robots, other bullets, etc), a much better gravity.
|
|
|
|
elix
Senior Newbie 
|
 |
«
Reply #9 - Posted
2009-04-04 11:03:25 » |
|
good news  this solves the problem: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| var gamelogics = Timeline { repeatCount: Timeline.INDEFINITE keyFrames: KeyFrame { time: 10ms action: function() { if((robot.translateY + robot.height) < 450){ robot.translateY+=4; } if(upkey){ robot.translateY-=5; } else if(downkey){ robot.translateY-=4; } if(rightkey){ robot.translateX += 2; } else if(leftkey){ robot.translateX -= 2; } for(b in bullet){ if(b.translateX > 5000){ delete b from bullet; } else b.translateX+= 10; } } } } |
|
|
|
|
|
Games published by our own members! Check 'em out!
|
|
elix
Senior Newbie 
|
 |
«
Reply #10 - Posted
2009-04-04 11:33:14 » |
|
Setting time parameter in keyframe is critical but I don't know how to determine the most accurate value. I tried setting canSkip parameter in your game and saw that how it slows down the application. Something came to my mind, may be this can be used to calibrate the value of the time parameter. If this(canSkip) parameter changes the speed of your application too much it means many timecycles are skipped. If that doesn't change the speed of the application too much than the value is appropriate, may be... only an idea.
|
|
|
|
|
zammbi
|
 |
«
Reply #11 - Posted
2009-04-07 13:07:42 » |
|
I have improved it but, found this little piece of info: http://blogs.sun.com/jtc/entry/node_count_and_javafx_performanceWhich I thought as much... Makes my game a lot harder to do now. I'm not making a crappy puzzle game for the contest  I'm currently a little suck, I'm using fxz files for the art, which are nodes when loaded. If I wanted to use then as tiles, how would I do that? It seems I can only use a node once, therefore my map wont fully print.
|
|
|
|
zammbi
|
 |
«
Reply #12 - Posted
2009-04-08 06:08:34 » |
|
After a lot of searching I found I needed to do: 1
| Duplicator.duplicate(node) |
But does that duplicate the image too?
|
|
|
|
jcon
|
 |
«
Reply #13 - Posted
2009-04-08 16:04:31 » |
|
The Duplicator.duplicate() will duplicate a node as you mentioned. If the node has an ImageView node inside it its graph, it should duplicate the underlying image as well.
Node performance is slower than image based designs as pointed out in the article you linked. In some cases though, you don't have to rely on making your entire design images. Sometimes you can greatly improve performance by simply having the JavaFX engine convert your nodes to a bitmaps by setting the cache property on your nodes to true. I have had good luck with that approach whenever I'm applying a lot of static effects to nodes that don't need to be redrawn all the time.
|
|
|
|
|
zammbi
|
 |
«
Reply #14 - Posted
2009-04-08 16:45:10 » |
|
The Duplicator.duplicate() will duplicate a node as you mentioned. If the node has an ImageView node inside it its graph, it should duplicate the underlying image as well. What I mean is that would it share the image data , instead of making a copy and using more ram? If I use the same copy of the node for 100 tiles on a map, will it use more ram? I have also made sure that the cache is set to true for all my static nodes.
|
|
|
|
brackeen
|
 |
«
Reply #15 - Posted
2009-04-08 17:42:01 » |
|
Node performance is slower than image based designs as pointed out in the article you linked. This isn't true for all 2D scenegraphs - Node-based systems can be much faster because dirty rectangles (invalid regions) can be computed automatically, therefore only changed regions of the screen need to be drawn (instead of drawing every pixel every frame). Of course it's possible to compute changed-regions by hand in immediate-mode image systems, but who would want to do that? The fact the JavaFX isn't good with a large number of Nodes is a huge bug. Luckily trembovetski mentioned this will be fixed in JavaFX around the time of JavaOne.
|
|
|
|
|
|
|
trembovetski
|
 |
«
Reply #17 - Posted
2009-04-08 19:08:22 » |
|
Interestingly, tracking dirty regions (and bounds) could take lots of time. Just re-rendering every node from scratch can be faster.
Yes, if you have complicated nodes with effects, it's better to cache them.
Dmitri
|
|
|
|
|
brackeen
|
 |
«
Reply #18 - Posted
2009-04-08 20:58:57 » |
|
Interestingly, tracking dirty regions (and bounds) could take lots of time. Just re-rendering every node from scratch can be faster.
PulpCore tracks dirty regions, and it's the single best optimization in the library. Even in some hardware-accelerated apps where overdraw can be a issue, it is worth it. Swing basically does it with the RepaintManager. JavaFX should do it too!
|
|
|
|
|
trembovetski
|
 |
«
Reply #19 - Posted
2009-04-08 21:39:23 » |
|
PulpCore tracks dirty regions, and it's the single best optimization in the library. Even in some hardware-accelerated apps where overdraw can be a issue, it is worth it. Swing basically does it with the RepaintManager. JavaFX should do it too!
It does. Dmitri
|
|
|
|
|
zammbi
|
 |
«
Reply #20 - Posted
2009-04-12 08:28:55 » |
|
New problem. I want to scroll the map like so: 1 2 3 4 5 6 7 8 9 10
| Group: content: bind[ map robot bullet gameObject ] translateX:bind -robot.translateX + centerPosX translateY:bind -robot.translateY + centerPosY } |
But this causes major lag if its moving the map. The map itself is a Group that has cache on, so it should be just a big static image... How else should I scroll a map?
|
|
|
|
trembovetski
|
 |
«
Reply #21 - Posted
2009-04-12 09:31:51 » |
|
How large is the map?
|
|
|
|
|
zammbi
|
 |
«
Reply #22 - Posted
2009-04-12 09:45:33 » |
|
Currently 800x600(the size of the game window).
Later Ill have maps larger then that of course but I currently don't sort out which nodes need to be removed from the map when not seen.
|
|
|
|
zammbi
|
 |
«
Reply #23 - Posted
2009-04-12 10:09:07 » |
|
I have improved it a little bit by spliting the timeline like so: 1 2 3 4 5 6 7 8 9 10 11
| var windowMove = Timeline { repeatCount: Timeline.INDEFINITE keyFrames: KeyFrame { time: 10ms action: function() { canSkip:true; g.translateX = -robot.translateX + centerPosX; g.translateY = -robot.translateY + centerPosY; } } } |
But still uses a heap of cpu. Don't see it running on anything that's not a new computer atm. Increasing the time does lower the cpu but it just makes it look horrible. Its also just using temp graphics which are just rectangles. I haven't got my SVG art from my artist yet.
|
|
|
|
aNt
|
 |
«
Reply #24 - Posted
2009-04-12 19:00:24 » |
|
try using g.transforms = [translate(....)] I have improved it a little bit by spliting the timeline like so: 1 2 3 4 5 6 7 8 9 10 11
| var windowMove = Timeline { repeatCount: Timeline.INDEFINITE keyFrames: KeyFrame { time: 10ms action: function() { canSkip:true; g.translateX = -robot.translateX + centerPosX; g.translateY = -robot.translateY + centerPosY; } } } |
But still uses a heap of cpu. Don't see it running on anything that's not a new computer atm. Increasing the time does lower the cpu but it just makes it look horrible. Its also just using temp graphics which are just rectangles. I haven't got my SVG art from my artist yet.
|
|
|
|
|
zammbi
|
 |
«
Reply #25 - Posted
2009-04-14 04:41:37 » |
|
Thanks that improved it a little. But still doesn't give me much room for bullets. I can only have 10 on screen. Will the performance be improved in this area in the next update? Also seems that insert is slow when working with a lot of nodes. But I don't this I have this issue. http://piliq.com/javafx/?p=864
|
|
|
|
zammbi
|
 |
«
Reply #26 - Posted
2009-04-16 13:04:42 » |
|
What's the best way to keep track of nodes(my tiles) to keep on screen? It seems I'm unable to track them how I want. Which is have my whole map as nodes in a group and then make another group for viewing and share those nodes with that group that only needs to be seen. But seems you can't share nodes with more then one group? This only will work if I duplicate the node. Which will just slows everything down. So for now I have to add the whole map to the screen.
Wish there was a example somewhere to explain how do to this....
|
|
|
|
trembovetski
|
 |
«
Reply #27 - Posted
2009-04-17 01:22:58 » |
|
What's the best way to keep track of nodes(my tiles) to keep on screen? It seems I'm unable to track them how I want. Which is have my whole map as nodes in a group and then make another group for viewing and share those nodes with that group that only needs to be seen. But seems you can't share nodes with more then one group? This only will work if I duplicate the node. Which will just slows everything down. So for now I have to add the whole map to the screen.
Wish there was a example somewhere to explain how do to this....
Create a sequence containing nodes that are [not] supposed to be seen - don't create a Group - it's a node in a scenegraph. A node can have only one parent. Add or remove nodes into this sequence (you could do it though binding automatically, too). You could also add a trigger - if a node is added, it's 'visible' automatically becomes false.. you could also bind a visibility of a node to its bounds intersecting the "game screen", or any other condition (like it being present in certain sequence).
|
|
|
|
|
zammbi
|
 |
«
Reply #28 - Posted
2009-04-17 06:06:36 » |
|
Oh I didn't know about the 1 parent rule. Thanks, Ill try that out and see if that solves my problem.
|
|
|
|
zammbi
|
 |
«
Reply #29 - Posted
2009-04-17 10:01:51 » |
|
I found adding/removing nodes from a scene slower then showing the whole map, so for now I have just set there visibility.
You said a node can't have more then one parent. Then what's the best way to add a second screen to view the same object? In my case a 2nd player.
|
|
|
|
|