Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 17:09 20 May 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Help with using Sprite for the first time

Author Message
Nimue

Guru

Joined: 06/08/2020
Location: United Kingdom
Posts: 367
Posted: 01:40pm 24 Aug 2020
Copy link to clipboard 
Print this post

Hi all

I am attempting to use SPRITEs for the first time (as a number geek I only every program for fun in "text" mode with the output normally being numbers or similar).

I have ported some old code to simulate the trajectory of a ballistic shell:

Const dt=.1 'timsslice, smaller = more accurate,but slower
Const v_int = 700 'muzzle velocity.  Rifle = 600m/s Tank = 1500
Const angle= 37 'launch angle in degrees
Const theta = angle*PI/180 ' convert degrees to radians
Const A_m = 0.00004 ' expeimental drag factor from Bennett
Const nmax = 10000 ' number of iterations
Const A_m2 = 0.004 ' surface area of projectile
Const wind =-35 'wind speed. 40 = hurricane -ve means headwind
Const rho = 1.2 ' density of air
Const wind_force = (0.5*A_m2*rho*wind^2*dt)

max_x = 25000
max_y = 9000

mode 1,8
cls

Function round(num,dp)  ' provids proper rounding

 exp= 10^dp
 n = num* exp
 If n >= 0 then
   n = sgn(n) * (abs(int(n+0.5)))
 ElSE
   n= sgn(n) * (abs(int(n-0.5)))
 End if

 round = n / exp
End function

Dim x(nmax), y(nmax) ' arrays to stor x and y positon

Sub calculate

 x(1) = 0
 y(1) = 0
 vx = v_int * cos(theta)
 vy = v_int * sin(theta)

 for i = 2 to nmax
   x(i) = x(i-1)+(vx*dt)  'calculate new x based on previous
   y(i) = y(i-1)+(vy*dt)

   f=A_m*sqr(vx^2+vy^2)

   vy = vy - (9.8*dt)-(f*vy*dt)
   vx = vx - (f*vx*dt)+(wind_force*sgn(wind))

   if y(i) <=0 then
      index=i
      exit for
   end if

   if y(i) > max_height then max_height = y(i)

 next i

xrange = (x(i)+x(i-1))/2


print "Range = " round(xrange,0) "m"
print "Max Height = " round(max_height,0) "m"
print "Index = " index
end sub

calculate()
axes()
draw()


sub axes()
line 0,0,0,600,3
line 0,550,650,550,3

end sub


sub draw()
for i = 1 to index
 pixel((x(i)/25000)*650)+3,(550-((y(i)/max_height)*550))

next i
End sub

Text 700,100,"Range "+ str$(round(xrange,0))


The code takes drag and wind into account.

Very rough at the moment.

How would I go about adding a SPRITE animation that follows the trajectory as it is drawn -- a cannon ball would be easiest as there would be no orientation issues at the top of the trajectory.

Total newbie with regard to this - will poke around the programs posted here to get insight from their code.

Any help greatly recievd.

Cheers
Nim
Entropy is not what it used to be
 
capsikin
Guru

Joined: 30/06/2020
Location: Australia
Posts: 341
Posted: 01:59pm 24 Aug 2020
Copy link to clipboard 
Print this post

There's 4 main parts:
Loading the sprite graphics, drawing the sprite the first time, moving the sprite, erasing the sprite at the end.

It's relatively simple since you don't need overlapping sprites or to change the background underneath the sprite.

Loading the sprite graphics, it may be easiest to draw it somewhere on screen with the CIRCLE command, then use SPRITE READ to read the sprite graphics from the screen.

Drawing the sprite for the first time, and moving the sprite, both can be done with the SPRITE SHOW command.

Erasing the sprite at the end, if you want to do this, can be done with the SPRITE HIDE command.

For moving the sprite, an alternative is SPRITE NEXT then SPRITE MOVE. You don't need this for just a single sprite, but examples you find may do this as it caters better for multiple overlapping sprites.

More details on the uppercase commands I've listed are in the manual (and of course others are welcome to chime in with more info)

additional: if you want a better graphic for the sprite than just circles, SPRITE LOAD is a good option, to load it from a text file. The format's not detailed in the manual, so you can check out "Graphics Programming on the CMM2" and/or example programs that use it. Or it's specified in the original Colour Maximite MMBasic Language Manual, apparently.

additional: I linked to Graphics Programming on the CMM2 from the wiki
Edited 2020-08-25 00:27 by capsikin
 
Nimue

Guru

Joined: 06/08/2020
Location: United Kingdom
Posts: 367
Posted: 02:30pm 24 Aug 2020
Copy link to clipboard 
Print this post

Thank you @capsikin >> good pointers.

I used that (and a look at the Lander prog listed before) and have this -- it works fine, but the cannon ball "tears" as is moves across the screen.

What techniques can I use to make it smoother?

Sorry for the really basic Q's

Const dt=.5 'timsslice, smaller = more accurate,but slower
Const v_int= 700 'muzzle velocity.  Rifle = 600m/s Tank = 1500
Const angle= 45 'launch angle in degrees
Const theta = angle*PI/180 ' convert degrees to radians
Const A_m = 0.00004 ' expeimental drag factor from Bennett
Const nmax = 10000 ' number of iterations
Const A_m2 = 0.004 ' surface area of projectile
Const wind =-35 'wind speed. 40 = hurricane -ve means headwind
Const rho = 1.2 ' density of air
Const wind_force = (0.5*A_m2*rho*wind^2*dt)

max_x = 25000
max_y = 9000

mode 1,8
cls

page write 2
load png "cball.png"  'load sprite from file

image resize 0,0,110,111,0,0,20,20,2  'make it smaller -- should resize the file
sprite read 1,0,0,20,20,2  'read into sprite 1



page write 0

'sprite show 1,0,0,1

Function round(num,dp)  ' provids proper rounding
 exp= 10^dp
 n = num* exp
 If n >= 0 then
   n = sgn(n) * (abs(int(n+0.5)))
 ElSE
   n= sgn(n) * (abs(int(n-0.5)))
 End if

 round = n / exp
End function

Dim x(nmax), y(nmax) ' arrays to stor x and y positon

Sub calculate

 x(1) = 0
 y(1) = 0
 vx = v_int * cos(theta)
 vy = v_int * sin(theta)

 for i = 2 to nmax
   x(i) = x(i-1)+(vx*dt)  'calculate new x based on previous
   y(i) = y(i-1)+(vy*dt)

   f=A_m*sqr(vx^2+vy^2)

   vy = vy - (9.8*dt)-(f*vy*dt)
   vx = vx - (f*vx*dt)+(wind_force*sgn(wind))

   if y(i) <=0 then
      index=i
      exit for
   end if

   if y(i) > max_height then max_height = y(i)

 next i

xrange = (x(i)+x(i-1))/2


print "Range = " round(xrange,0) "m"
print "Max Height = " round(max_height,0) "m"
print "Index = " index
end sub

calculate()
axes()
draw()


sub axes()
line 0,0,0,600,3
line 0,550,650,550,3


end sub

sub draw()
sprite show 1,0,599,1  'put sprite onto screen

for i = 1 to index
 sprite next 1,((x(i)/25000)*650)-10,(550-((y(i)/max_height)*550)-10)
 pause 5  
 sprite move
next i

End sub


Text 700,100,"Range "+ str$(round(xrange,0))

Entropy is not what it used to be
 
Nimue

Guru

Joined: 06/08/2020
Location: United Kingdom
Posts: 367
Posted: 02:32pm 24 Aug 2020
Copy link to clipboard 
Print this post

Thanks for the link to the graphics guide - rtfm!!
Entropy is not what it used to be
 
capsikin
Guru

Joined: 30/06/2020
Location: Australia
Posts: 341
Posted: 03:32pm 24 Aug 2020
Copy link to clipboard 
Print this post

  Nimue said  Thank you @capsikin >> good pointers.

I used that (and a look at the Lander prog listed before) and have this -- it works fine, but the cannon ball "tears" as is moves across the screen.

What techniques can I use to make it smoother?


One technique is to render to a separate page (PAGE WRITE to choose the page), then copy to page 0 (PAGE COPY) at screen blanking time (MODE to set the screen blanking interrupt). Lunar lander does the rendering to a separate page but not the screen blanking timing. matherp recently posted a demo that does it.

tennis.zip from here:
https://www.thebackshed.com/forum/ViewTopic.php?FID=16&TID=12600#153265

Another idea I had is to skip the SPRITE MOVE commands when the area around the sprite is being output to the display. Could use GETSCANLINE "This will report on the line that is currently being drawn on the VGA monitor. Using this to time updates to the screen can avoid timing effects caused by updates while the screen is being updated".
 
vegipete

Guru

Joined: 29/01/2013
Location: Canada
Posts: 1085
Posted: 04:05pm 24 Aug 2020
Copy link to clipboard 
Print this post

Lunar Lander does use screen blank timing.

The command "PAGE COPY <source>,0,B" is key.
(Note the manual indicates "TO" between the source and destination, but a comma works just as well.)

The idea is to do all your drawing on a non-visible page. Only page 0 is visible. When you have finished drawing, you copy the image page to page 0. The extra parameter "B" indicates to pause your program until the next vertical blanking, then perform the copy and finally release execution back to your program. The manual gives a couple of other options for the PAGE COPY command too.

The key is to absolutely not be changing the source image while the page copy is happening if you are not using the "B" parameter.
Visit Vegipete's *Mite Library for cool programs.
 
capsikin
Guru

Joined: 30/06/2020
Location: Australia
Posts: 341
Posted: 04:12pm 24 Aug 2020
Copy link to clipboard 
Print this post

  vegipete said  Lunar Lander does use screen blank timing.

The command "PAGE COPY <source>,0,B" is key.


Sorry, my mistake, I only checked for SETTICK and MODE interrupts.
  Quote  
(Note the manual indicates "TO" between the source and destination, but a comma works just as well.)

The idea is to do all your drawing on a non-visible page. Only page 0 is visible. When you have finished drawing, you copy the image page to page 0. The extra parameter "B" indicates to pause your program until the next vertical blanking, then perform the copy and finally release execution back to your program. The manual gives a couple of other options for the PAGE COPY command too.

The key is to absolutely not be changing the source image while the page copy is happening if you are not using the "B" parameter.
 
x4nd
Newbie

Joined: 05/07/2020
Location: United Kingdom
Posts: 11
Posted: 06:48pm 24 Aug 2020
Copy link to clipboard 
Print this post

An alternative to perhaps look at is to use the MODE command with a function that gets run in the vblank period.  That function would do your calculation for the next frame.  As long as it was quick, you'd get it all ready for the next screen refresh and so suffer no screen tear.
If only there were more hours in the day..
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024