I'm making a game using the dev kit mouse and want a line to go from the character to the mouse location
But I can't figure out what place that the line needs to end in order for the line to end before it gets to the player
http://imgur.com/a/vscVn
on the top is what I have, and on the bottom is what I want
How do I find/get the variable to stop the line short of the player?
Sorry for all the questions I've been asking recently
two ways I can think of off the top of my head:
- use vectors (you'd have to add a whole 2D vector class/library to your code, but this can be super useful for lots of gamedev things so you might consider it). this way you can do something like the following (assuming you have player position and mouse position stored as 2D vectors):
local dir = player.position - mouse.position dir:setmagnitude(15) local dest = mouse.position + dir line(mouse.x, mouse.y, dest.x, dest.y) |
- draw a line manually, pixel by pixel. the bresenham line algorithm is popular and easily googleable. then you can just stop drawing pixels early when you hit a certain length. this is perhaps simpler than the vector approach because it doesn't require adding a whole library to your game, just one function. or I guess you could also do that for the vector math stuff...distill it down to just one function that you need
Since the background is all blue you could:
- Draw the line between the player and the mouse location.
- Draw a blue circle at the player position with the radius you want.
- Draw the player character on top of the circle.
However, if you're going to use tiles for the background later then this solution won't work.
Hey pixel.. these suggestions would work but here are some simpler ideas.
Is the line always going to be in the top right corner of the character sprite? If so..
line(mouse, mousey, player.x+7,player.y-1,7) |
If your character isn't 8 pixels wide then just adjust the number you add to player.x.
Or if you want something even easier, just draw the line, THEN draw your sprite on top of it. That way you'll just draw over the parts of the line that overlap with your sprite.
Hope that helps..
EDIT: Oops, I thought you had the last image and wanted it to work like the first.
I'm not going to write code for you, but I'll tell you the sequence to use. Learning any necessary math is left as an exercise, but on the bright side, nothing here is very difficult and plenty of resources to learn the math are available.
-
Pick a minimum distance. If you're using an 8x8 player sprite and the player location is in the center of the sprite, then the longest distance that's still inside the sprite is from the center to a corner. The length of a line to the corner is √2 (or about 1.41) longer than a line to the edge. In an 8x8 sprite the line from center to edge is 4 pixels long, so if you pick at least 6 (1.5x) you should be outside of the player, even diagonally. Or be generous and pick 8 or 10 to leave a definite gap.
-
Use the pythagorean theorem to get the linear distance between the mouse cursor and the player center.
-
Now you know the length of the entire line (we'll call it L), and the length you want to chop off at the player end (we'll call it P). You can slide a point from the player location to the mouse cursor using linear interpolation, or lerp for short. Lerping uses a fraction to say where the point is between the two, e.g. 0.1 is close to the player and 0.9 is close to the camera. You'll want to use a fraction that represents your desired distance relative to the current distance, so interpolate from the player towards the mouse by the fractional value P/L. For instance, if you picked a minimum distance of 10 and the mouse is 50 pixels away from the player this frame, interpolate with 10/50 or 0.2 for this frame.
-
Draw a line between the mouse position and your interpolated position. You might want to make sure the overall length L is greater than P to begin with so your math doesn't go funny, trying to draw in the wrong direction. If it is, maybe just don't draw the line.
- Done.
As mentioned you can use a vector, or (similarily) you can use the angle towards the player:
local angle=atan2(player.x-mouse.x,player.y-mouse.y) line(mouse.x,mouse.y,mouse.x+cos(angle)*8,mouse.y+sin(angle)*8,7) |
"*8" is the length of the line. Limiting the length so it doesn't cross the player requires a distance check.
Actually, that post I made is TL;DR material and thus useless for learning.
Here's a complete demo, with comments to learn from, instead:
--mouse enable poke(0x5f2d,1) --initial player pos px,py=64,64 --inner circle size mindist=10 function _update60() --sample mouse pos mx,my=stat(32),stat(33) end function _draw() cls() --============================ -- begin code you care about --============================ --vector from player to mouse local dx,dy=mx-px,my-py --get length of vector via --pythagorean theorem local dist=sqrt(dx*dx+dy*dy) --only draw a line if mouse --is outside inner circle if dist>mindist then --how much of the line our --inner circle chops off local frac=mindist/dist --new point on inner circle local ix,iy=px+dx*frac,py+dy*frac --render line from inner --circle to mouse line(ix,iy,mx,my,12) end --============================ -- end code you care about --============================ --draw player sprite, --centered across px,py spr(0,px-4,py-4) --draw a mouse cursor line(mx,my,mx+4,my+4,7) line(mx,my,mx,my+6) line(mx+3,my+4,mx,my+5) end |
Note:
this is the way I'd want to do it on a real platform, because aside from the sqrt(), this is simple math that runs very quickly on a real processor. Using other code, such as the bit suggested using atan2()/cos()/sin(), may actually be more appropriate in some cases on pico-8, because trigonometric functions run quite quickly on pico-8, but slowly on a real platform.
I prefer to suggest methods that are universal, but sometimes on pico-8 you're better off taking advantage of its special characteristics, which is also a valuable skill for a game dev to have.
[Please log in to post a comment]