Hello :)
(Forever) Beginner level programmer here!
I have been trying to make a top down driving game, and rather than reinvent the wheel I figured I could take some existing carts and use the code to make a player that uses a sprite that can rotate, and move forward and backward.
I found this post for the sprite rotation, which works exactly as I would like, although I can't really grasp how the function is working: https://www.lexaloffle.com/bbs/?pid=52525 (example1)
Then I found a cart of Asteroids by @mccolgst: https://www.lexaloffle.com/bbs/?tid=29903, stripped out all the stuff I didn't need (example2), and have been going between these 2 carts to try and combine the sprite rotation function with the desired movement.
Unfortunately I hit a wall and my latest effort was example3, but I'm quite lost honestly.
Can anyone shed some light on how these carts work and how I could go about applying a forward movement to a rotated sprite?
Many thanks in advance!
In the third cart in update_p(), your value for the change of angle is 0.1 (a tenth of one), whereas your value for the change of p.a is p.rotspeed, which is 30 (a twelfth of 360). As such these are not in sync.
This addresses that issue by calculating the change to angle by calculation from p.rotspeed. For example in the line ' angle+=p.rotspeed/360'
function update_p() if btn(0) then p.a-=p.rotspeed angle+=p.rotspeed/360 end if btn(1) then p.a+=p.rotspeed angle-=p.rotspeed/360 end p.a%=360 angle%=1 if(angle<0.005 or angle>0.995)angle=0 if btn(2) then p.x+=cos(angle) p.y+=sin(angle) --p.acc=true else --p.acc=false end --p.a=p.a%360 p.x+=p.dx p.y+=p.dy --p.dx*=p.friction --p.dy*=p.friction end |
There are also three extra lines in there:
p.a%=360 angle%=1 if(angle<0.005 or angle>0.995)angle=0 |
These just reset the angles to 0.
The first two use modular arithmetic; see: https://en.wikipedia.org/wiki/Modular_arithmetic
For example: 'p.a%=360' makes p.a wrap from 359 to 0.
The third line 'if(angle<0.005 or angle>0.995)angle=0' waits until angle is near 0, then corrects for any errors introduced from dealing with fractions.
Hey @remcode!
Thank you so much for your very timely and detailed response!!
Thanks a bunch for the explanation and link; lots more to learn here.
Bonus question - I was trying to emulate the movement in the second cart example (the one based on Asteroids), but again I cannot understand what the code is doing. It seems this is what controls the ships forward movement:
if btn(2) then
player.dx+=-sin(player.aim-1).15
player.dy+=cos(player.aim-1).15
end
Again I am not totally clued on why you would interchange sin and cos functions to the x/y values, or what the additional values at the end are affecting. I pasted this snippet into the below cart, and I also tried swapping out p.x and p.y to p.dx and p.dy, but then the ship goes very fast:
p.dx+=cos(angle)
p.dy+=sin(angle)
So I tried giving a max value for dx/dy but something is off with the direction of movement again.
What could be the simplest way of applying the feeling of accelerated movement to the ship?
Many thanks again!
By the way, completely amazed by this forums willingness to help newbies like myself. Great community :)
btw that rotation code is slow/outdated now.
suggest to switch to: https://www.lexaloffle.com/bbs/?tid=38548
For more gradual acceleration, try
function update_p() --turn ship if btn(0) then p.a-=p.rotspeed angle+=p.rotspeed/360 end if btn(1) then p.a+=p.rotspeed angle-=p.rotspeed/360 end --wrap angle p.a%=360 angle%=1 if (angle<0.005 or angle>0.995) angle=0 if btn(2) then p.dx+=cos(angle)*.15 p.dy+=sin(angle)*.15 end --move ship p.x+=p.dx p.y+=p.dy --wrap to screen local width=32 if p.x<0-width then p.x=127 end if p.y<0-width then p.y=127 end if p.x>127 then p.x=0-width end if p.y>127 then p.y=0-width end --decrease acceleration p.dx*=p.friction p.dy*=p.friction end |
If the ship is slowing too fast, you might also want to change your value for friction to 0.99 or 0.999, so more of the speed is preserved.
If you're looking to gain a deeper understanding of what's going on, so you can more easily make such changes, try the following links:
youtube: 'Coding Math' channel
youtube: 'games programming physics' search
Some things will be more or less relevant with Pico-8 (see the Pico-8 manual: Quirks); particularly:
Pico-8 cos and sin expect/use angles from 0 to 1 (the 'Coding Math' channel mentions radians).
Pico-8 inverts the result of the sin function, with the y-axis already inverted, the effect is that the result it gives is in the rotation direction you might expect (anti-clockwise). (In episode 2, the 'Coding Math' channel presenter says that you will find rotation going the other way.)
Many coding channels will be looking at languages other than Lua, and other than Pico-8's altered subset.
I realize Pico-8 has limited resolution, however is there any way to get around these jaggies, @simonwilson ?
@dw817 I'm not the expert on this but I think since the sprite is such a low resolution already, the function is doing its best to make it look correct at all angles, but there is a limit...
If you want something with less jagged pixels then try drawing a larger sprite and that should reduce the effect. Otherwise try the alternative rotation function in the link above from @freds72.
Hi @simonwilson. I tried his program, still getting jaggies. i guess what I'm looking for which likely hasn't been done yet is something to DITHER the rotation. That is give them softer edges based upon how sharp they appear in rotation.
https://www.lexaloffle.com/bbs/?pid=106060#p
. . .
Just now thinking, how about a program to do a clean rotation every 22.5 degrees ? Does not need fine 0-359.
So it could rotate from 0 to 22.5, 45, 67.5, 90, 112.5, 135, 157.5, 180, 202.5, 225, 247.5, 270, 292.5,315, 337.5 and back to 0 again. 16 total rotation states.
Back again!
So.... Movement is ok, sprite rotation is ok... But now I cannot make the background pixels transparent.
I checked the spr_r function and I see that it uses a for loop to set the pixels in each frame, so when it comes to the Pset function,
I made the colour a local variable, and tried to set the colour 14 to transparent.
if (xx>=0 and xx<sw and yy>=0 and yy<=sh) then
local colour = sget(sx+xx,sy+yy)
pset(x+ix,y+iy,colour)
if colour == 14 then
palt(14,true)
palt(0,false)
end
print(colour,10,40)
end
This didn't work, so I checked the value of Colour by printing it, and sure enough it was the correct value. But then if I set Colour to another value, the numeric value changes, but not the colour it had been set to.... What?!
I thought this would solve the issue but I cannot see why the number can change, but not the colour...
I was just about to give up on this but I followed your link with the new function and have managed to implement it to my cart... so finally it is working as I had hoped for. Many thanks!
@dw817 As you can see in the latest for my cart above, I used the same rotation function but the jaggies are definitely present and I don't have a way around it. The dithering would be nice, but do you think it could be achieved with the limited colours?
I like your idea with the preset 16 rotation states - hope to hear if you decide to develop it more.
check my answer to @dw817 in this other thread
[Please log in to post a comment]