Turning of 2D Graphics

Blitz3D Forums/Blitz3D Beginners Area/Turning of 2D Graphics

Hello, everybody, i am writing a space shooter and want my ship to behave like in Asteroids. Im working on that and found lots of help... but if my ship turns the game slows drastically. The only command i know is rotateImage() which is too slow, and if i put all 360 degrees of the turning into an array before starting the game it takes a long time to start (especially since i have 16 different ships and stations which must turn). The search-function of this site is offline and i do not have the time to read every post in here... can anyone tell me how i can make my ships turn in realtime or how to make a loading-screen?
Thanks a lot in advance :)

Try only 36 frames.

Or, since this is 3D, you could 3D accelerate it.

Thanks for the reply.
The rotating must be smooth... even with 72 frames the rotating looks ugly... and there is nothing better to destroy the playability of a game.
I dont think i could go lower then 180 frames, but that doesent lolve the problem of the command "RotateImage()" being way too slow.
And it is not 3D, it is 2D... can i accelerate that too? (if yes, how?)

You could fake 2D using 3D.

But you cant really accelerate 2D.

Again, thanks for the reply.
But i have not yet advanced to 3D-Programming, so i have no idea how i could do what you suggest. But honestly thats not important, because i found a solution... My Loading-Screen now works fine and i use 180 steps. The Game will take some time to load, but now it tells the User that it takes time and how far it has advanced loading. In-Game it works perfectly and fast (and easy to programm... :))
The remaining question is, is there another way to make a 2D-Bitmat rotate except RotateImage()?

RotateImage() is very slow in real time.
The best way to rotate an image is to use a precalculated array. In other words before your main loop, you make an array of 360 (because there is 360 degrees in a circle). Then you iterate through it with a For, Next statment. In each iteration you copy your image and rotate it. There is now 360 frames of the image rotated 1 degree in your array. And last you use drawimage(your frame rotation image here),400,300.

Easier done than said...
Const rotation_frames = 360 ; This does not need to be 360 it can be 16, or 32, or 4 anything that divides 360 equaly.

dim player_ship(rotation_frames) 
For I = 0 to rotation_frames - 1 
player_ship(I) = CopyImage(the handle to your image)
rotateimage(I),I*360/rotation_frames
next 

;Now you need a variable to keep track of the rotation frames 
rot = 0

while not keydown(1)
if keydown(rightkey)
     rot = rot +1
endif 
if keydown(leftkey) 
    rot = rot -1
endif 
Drawimage player_ship(rot),posx,posy

flip
wend
end 



Err looks like you already figured it out and I was to slow.

Why don't you write some code to rotate and export the animation frames to an animstrip? Then all you have to do is use LoadAnimImage to reload it, instead of making the player wait while your program generates it each time.

GfK, thanks for pointing me to the most logical solution... my nose is big and it hid that solution in front of my face ;))
And I wont have to recode much, either...

I wrote a piece of code to rotate an Image and export it to an animstrip. Now i would like to share it with u all, but... can u tell me how to make such a nice black window?

Forum codes

As you will see, i commented the code. It is tested to animate squared pictures.
A short summary of what it does:
1. it loads the picture you want it to animate
2. it generates a bigger picture and copies the original into the bigger one (otherwise the edges would get cut off)
3. it rotates the picture
4. it saves the rotated picture into an animstrip (which is nothing more then a really big picture)

Hint: be careful with big pictures... blitz seems to have a maximal number of pixels a picture can have that it sees it completely. (at least with LoadAnimImage())

The Code:
; ---------------------------------------------------------------------------------------------
; --------------------------------- WRITTEN BY BLITZADICT -------------------------------------
; ---------------------------------------------------------------------------------------------

; Die Variablen werden gesetzt

Global TitelDesProgrammes$ = "Animator"
SeedRnd MilliSecs()

Const Breite = 1024
Const Hoehe = 768
FarbTiefe = 0
FensterModus = 1

; Konfiguration des Fensters + Programmtitelausgabe

Graphics Breite, Hoehe, FarbTiefe, FensterModus
AppTitle TitelDesProgrammes$

; ----------------------- COPY THE CODE FROM HERE IF U WISH TO IMPLEMENT -----------------------------
; ----------------------- IT INTO YOUR OWN -----------------------------------------------------------

; the variables below must be global, because the program wont run otherwise
Global AnzahlGrade = 360; change here to have the animation more or less steps (more has not been tested)
Global MultiplikationsFaktor = 360/AnzahlGrade  ; that the picture gets animated in a full circle
Dim AnimationBild(AnzahlGrade)
	
AnimFont = LoadFont("Times New Roman", 30, 0, 1, 0)
SetFont AnimFont

Function AnimationenGenerieren(BildName$, ZielBildName$ = "Leer"); The first variable is the name of the picture you want to animate and the secound the name you want the animation to be saved with
	
	GrundBild = LoadImage(BildName$) ; Loads the picture to be animated
	MaskImage GrundBild, 255, 255, 255
	
	Bild = CreateImage((ImageWidth(GrundBild)+22), (ImageHeight(GrundBild)+22)) ; Because of the rotation, the picture gets copied into another, bigger one (otherwise the edges might get cut off)
	SetBuffer ImageBuffer(Bild)
		Color 255, 255, 255 ; draws a rect of white color... this is the color which gets ignored
		Rect 0, 0, ImageWidth(Bild), ImageHeight(Bild)
		DrawImage GrundBild, 11, 11
	SetBuffer BackBuffer()
	
	MidHandle Bild ; The handle of the Picture to be rotated gets set to the center
	MaskImage Bild, 255, 255, 255 ; The color white gets ignored

	Animation = CreateImage((AnzahlGrade*ImageWidth(Bild)), ImageHeight(Bild))
	
	SetBuffer ImageBuffer(Animation) ; The Animstrip gets created and filled white (i always ignore white)
		Color 255, 255, 255
		Rect 0, 0, (360*ImageWidth(Bild)), ImageHeight(Bild)
	SetBuffer BackBuffer()
	
	For Grade = 0 To AnzahlGrade-1 ; 0 = 360
		Cls
		AnimationBild(Grade) = CopyImage(Bild)
		RotateImage AnimationBild(Grade), Grade*MultiplikationsFaktor
		Color 255, 255, 255
		Text 20, 20, "Rotating Image '" + BildName$ + "' " + Grade + " Steps done."
		Flip
	Next

		For Grade = 0 To AnzahlGrade-1 ; 0 = 360
			
			SetBuffer ImageBuffer(Animation)
			
				DrawImage AnimationBild(Grade), ((Grade * ImageWidth(Bild))+1*ImageWidth(Bild)/2), 0+(1*ImageHeight(Bild)/2)
			
			SetBuffer BackBuffer()
			
			Cls 
			
			Color 255, 255, 255
			Text 20, 20, "Painting: " + Grade + " Steps done."
			Flip
			
		Next
	
	Cls
	Text 20, 20, "Saving"
	Flip
	
	If ZielBildName$ = "Leer" Then ; If you dont give the AnimStrip a specific name, the name of the animated picture plus " Animated.bmp" gets used
		
		LaengeDesNamens = Len (BildName$)
		ZwischenName$ = Left$(BildName$, (LaengeDesNamens-4))
		NeuerZielBildName$ = ZwischenName$ + " Animated_" + AnzahlGrade + ".bmp"
		SaveImage Animation, NeuerZielBildName$
		
	Else ; If you give the AnimStrip a specific name, it gets used
		
		SaveImage Animation, ZielBildName$
		
	End If
	
End Function

Repeat
	
	Color 0, 0, 0
	Cls
	Color 255, 255, 255
	Text 30, 30, "Please Press 'a' to start the Animation"
	Text 30, 60, "Please Press 'q' to end this program"
	Flip

	If KeyHit(30) Then
		AnimationenGenerieren("Picture") ; enter here the name of the picture you want to animate
	End If
	
	If KeyHit(16) Then
		End
	End If
	
Until KeyHit(1)


It surely is not perfect, but it runs perfect. And since this creates animstrips you then use in your programs, speed is not of the essence here ;)

Feel free to use the code to your liking.

/edit: corrected a bad grammatical error :)