Recently I discovered it is very easy to have objects move towards (or away from) any points inDragonRuby.
This post might be a little easier if you've already read my post onmoving in arbitrary directions, but actually the code here is even simpler.
If I skip any explanations here, the concepts should have been coveredearlier in the series.
Setup
To get started, let's just output a square (roughly) in the middle of the screen.
args.grid.center_x
andargs.grid.center_y
are helpful for this instead of remembering/hardcoding the screen size.
In addition, the code usesargs.state.tick_count == 0
to do some setup on the first tick.
deftick(args)# On the first tick...ifargs.state.tick_count==0# Create a 50x50 pixel square in the middle of the screenargs.state.player={x:args.grid.center_x,y:args.grid.center_y,h:50,w:50}# Output that square on every tickargs.outputs.static_solids<<args.state.playerendend
Pretty basic!
(Note I'm skipping straight tostatic_solids
because that's what I'd prefer in a "real" game.)
Moving to a Point
Now we'll move the "player" to a given point - in this case where the mouse is. In typical DragonRuby fashion,args.inputs.mouse
can be used to as a point, even though it has a bunch of other information attached to it.
To get the angle from the player to the mouse, there is a very convenientangle_to
method! (Alsoangle_from
depending on which way you'd like to go.)
Just likeargs.inputs.mouse
, theplayer
solid can be treated as if it is a point, too.
One the angle is calculated,vector_x
andvector_y
will provide the magnitude to move in thex
andy
directions.
deftick(args)ifargs.state.tick_count==0args.state.player={x:args.grid.center_x,y:args.grid.center_y,h:50,w:50}args.outputs.static_solids<<args.state.playerend# Find angle from the square to the current location of the mouseangle=args.state.player.angle_to(args.inputs.mouse)# Move towards the mouse using the unit vectorargs.state.player.x+=angle.vector_xargs.state.player.y+=angle.vector_yend
And... that's it!! Less than 10 lines of code (without comments/spaces) and it just works.
So now let's make it more complicated...
Centering
It is annoying that the player moves so thebottom, right-hand corner meets the mouse, there is a simple fix: useanchor_x
andanchor_y
. DragonRuby will automatically use the anchor point for calculations.
To learn more about anchor points, see thisearlier post. But typically the values are set to0.5
which means "middle of the object".
deftick(args)ifargs.state.tick_count==0args.state.player={x:args.grid.center_x,y:args.grid.center_y,h:50,w:50,anchor_x:0.5,anchor_y:0.5,}args.outputs.static_solids<<args.state.playerendangle=args.state.player.angle_to(args.inputs.mouse)args.state.player.x+=angle.vector_xargs.state.player.y+=angle.vector_yend
Moving to Classes
I continue to prefer taking an object/class-based approach in my own code. This makes it much easier to manage as the code grows larger, even if it seems silly for these small examples.
In a little departure from previous posts, I am not walking through the code in detail. (Please check out my other posts in this series to learn more!)
The main difference from the above is adding aspeed
to the movement calculation. Other than that, this is how I generally move from simple code like the above into a structure more suitable (in my opinion) as the code.
classGameattr_gtkdefinitialize(args)# Separate setup method is easier if you need to# reset during the gamesetup(args)enddefsetup(args)# Since static_sprites persists between ticks,# need to clear it in case of resetargs.outputs.static_sprites.clear@player=Player.new(x:args.grid.center_x,y:args.grid.center_y,h:50,w:50,speed:2)args.outputs.static_sprites<<@playerenddeftick(args)@player.tick(args)endendclassPlayerattr_spritedefinitialize(x:,y:,h:,w:,speed:)@x=x@y=y@h=h@w=w@anchor_x=0.5@anchor_y=0.5@speed=speedenddeftick(args)angle=self.angle_to(args.inputs.mouse)@x+=angle.vector_x*@speed@y+=angle.vector_y*@speedendenddeftick(args)$Game||=Game.new(args)$Game.tick(args)end
One minor note if you actually run this code - the square will be white (default for sprites) instead of black (default for solids).
Top comments(1)
For further actions, you may consider blocking this person and/orreporting abuse