Attack of the Alien Space Beetles test v.81

Miscellaneous Forums/Blitz Showcase/Attack of the Alien Space Beetles test v.81

So I've gotten back to work on my space beetles game, and I'm attempting to get it completed before the end of February, and I thought I'd put this test version out there to see how it works for people.

Right now, the game does not have any "levels" or spawn enemies with any rhyme or reason. Every second or so it just randomly picks a random type and spawns it.

I've chosen to forego most traditional enemy attack patterns for more unqiue ones, so even in the final game there won't be many "chains" of enemies flying about on predefined paths. (The attack pattern for the red bird enemy is not finalized.)


http://raccoonrocket.com/blitz/asb-081.zip


Controls are as follows:

Mouse = Move, fire
Spacebar = Change background
PgDn = change weapon (rocket enabled currently causes you to fire slowly, but in the final game it won't affect your firing speed and the rockets may simply fire on their own for a preset time period)
F = toggle fullscreen/windowed. (Pressing alt when windowed will give you hack the mouse cursor, but maximizing the window currently breaks the mouse control.)


Besides the new enemy attacks, some of the enemy bullets now cause your ship to shake or slow down momentarily when they hit you.

Also, you can shoot powerups up to four times to juggle them in the air and each shot increments a multiplier for the number of points you get when you finally collect them. Shooting them five times blows them up and you get nothing. The direction they fly in when shot is always towards the middle of the screen so you don't lose them. :-)

Another small detail which you may not notice is that when the ameobas split each generation is allowed fewer splits. This is to prevent people from leaving one ameoba alive at the end of a level and allowing it to split and then shooing the copy repeatedly to get a high score.

The game is currenty set to load in fullscreen mode, using DirectX. If you have any problems with it, lemme know. It uses the same video mode as your desktop is set to.


Feedback/ideas appreciated!

I played the game till about 50K.
It's an addictive game even without the levels.

+Nice weapon 'freakout' when you pick up the xxx-barrel
+Smooth graphics
+Good looking backgrounds

~Then weapon freakout prevents you from picking up the loot or makes you shoot them 5 times :(

- Some enemies are so low on the screen that its damn near impossible to get them.

Looking forward to the final game which i really hope will include some bosses :)

*Also i would really like to know which tools you use to make those beautifull looking sprites.

..fart sound of one of the enemies makes me laugh like crazy...nice.. :)

I like that its widescreen, my screen cant scale to 4:3 which makes everything looked streched if its ot widescreen.

Graphics are great to.

I didn't even check the sound, yet, but it has a very neat look to it! Great style! Congrats...

Takes ages to return to the desktop after pressing escape, on my machine. I thought it'd crashed.

like the style !

Well done!

Gfxs:
- Support 4:3 resolutions as well.
- It's difficult to track bonusses as some "look" like enemies.
- I would love to see the background a bit less "static". E.g. via rotating planets, clouds, asteroids

Techincal:
- use tools such as OptiPMG to decrease the filesize of your graphics: http://optipng.sourceforge.net/
- use UPX to shrink your final executable: http://upx.sourceforge.net/
- when freeing your resources at the end of the game, make some kind of "waiting screen". - It really feels like your app is crashing.

for me when starting it goes to full screen and then immediately exits back to the desktop with no error. system info in the tag line.

Takes ages to return to the desktop after pressing escape, on my machine. I thought it'd crashed.


when freeing your resources at the end of the game, make some kind of "waiting screen". - It really feels like your app is crashing.



Yeah, that's a bug I posted about in the BlitzMax forum. It only happens in DirectX, not OpenGL, and has nothing to do with freeing anything.

(Right now the game is using DirectX because of a seperate issue where rendering in solid color doesn't work right in OpenGL so when you get slimed you turn yellow instead of green.)

I've tried to figure out exactly what's causing the slowdown, but so far no luck. I may create a workaround later by minimizing the window or something before shutting down. It won't make it shut down faster but at least you'll get back to the desktop quick.

Gotta concentrate on getting the game done though, as I've only got a couple months to finish it remaining.

for me when starting it goes to full screen and then immediately exits back to the desktop with no error.



Though the game defaults to fullscreen, it contains code which should switch it into windowed mode if no fullscreen mode can be set at the resolution which your desktop is running at. And the windowed mode is always 800x600 so any system should be able to handle that.

So... I have no idea why the game would simply exit after attempting to go fullscreen, unless DX is crashing when an invalid mode is attempted.

What resolution is your desktop set to? Do you have multiple monitors with the desktop spanned across them?

Yeah, that's a bug I posted about in the BlitzMax forum. It only happens in DirectX, not OpenGL.
Odd. No other bmax app I've tried has done this.

You think that's odd... I took the code I use in the game for setting up the graphics and windowed modes and switching between fullscreen and windowed, and and seperated it from all the gameplay code, and the delay doesn't occur!

Also, the delay occurs whether you exit the game, or toggle from fullscreen to windowed mode, and it happens in different places.

I think the cause is something to do with the amount of graphics being loaded, but I've tried loading and drawing a ton of graphics in the example as well and that failed to reproduce the problem.

Here's the example program which uses the same code as my game but doesn't reproduce the error:

SuperStrict

Import MaxGUI.MaxGUI 
Import MaxGUI.Win32MaxGUI 

' Includes:
	
	
' Globals:

	' Use Time% for game timing.  Time% is paused when the game is minimized and starts at 0, so it will not roll over for 23 days. 

	Global FPS%
	Global State%
	
	' Timing
	
		Global Time%, Time_Delta%, Time_Delta_Sec#, Last_Time_Delta%, Last_Time_Delta_Sec#
		Global System_Time%, Last_System_Time%

	' Frame smoothing
		
		Global Frames% = 1				' Initially the FrameTime array will only have one frame's time stored in it, but the array and this count of the number of values in it will be 
		Global FrameTime%[Frames]		' resized each frame to have more or less frames depending on the current framerate.
		Global Max_FrameTime%
		Global Frame%
		Global FrameDelay%

	Global Loop%
	Global IMG_Dust:TImage[100]

					
' Main:
		
	' Set the video mode.
	
		' Currently, we are setting the video mode to that of the desktop, and running the game fullscreen.  But it may be desirable to run the game at some other resolution so it can run
		' in a window, or run faster.  The scaling code will work no matter what resolution is used here, but it would not be desirable to use an aspect ratio for windowed mode which is
		' different from the 16:10 aspect ratio of the game, because there would be uneccessary letterboxing displayed.
	
		App.Create("Attack of the Alien Space Beetles!", ClientWidth(Desktop()), ClientHeight(Desktop()), 0, True, False)
		
		For Loop = 1 To 1
			IMG_Dust[Loop] = LoadImage("gfx\background\dust2.jpg")
		Next
			
	' Scale the graphics onscreen and display them letterboxed if needed.
	'	ProjectionMatrix.SetLetterBox(800, 500)

	SeedRnd MilliSecs() 
	System_Time = MilliSecs()
					
	Repeat
	
		Repeat 
			Last_System_Time = System_Time									' Store start time of last frame.
			System_Time 	 = MilliSecs()										' Get the current system time.  
			Time_Delta       = System_Time - Last_System_Time						' Calculate how long last frame took to render, in milliseconds.
			Time_Delta_Sec#  = Float(Time_Delta)/1000.0							' Convert frame time to seconds.
		Until (Time_Delta > 0) And (Time_Delta < 250)							' Handle unnaturally long pauses between frames gracefully.
								
		EventHandler()														' Process window events.
		
		If Not AppSuspended()
									
			Time = Time + Time_Delta											' Calculate current game time.  
			'Sprite.SetTimeStep(Time_Delta)									' Set the timestep for the sprites this frame.
									
			If App.Windowed Then ActivateGadget App.Canvas						' If windowed, make sure canvas stays active, or else polled input will go elsewhere.		

			UpdateMouse()													' Get mouse input.
			'StateSystem.Update()											' Update game.
			
			'Sprite.Update() 												' Animate sprites, do physics.

			SetClsColor 0, 0, 0												' Clear screen and draw sprites.
			Cls
			
			'Sprite.DrawAll()												' Draw the sprites.

			' Draw letterbox.
				ProjectionMatrix.DrawLetterbox()
									
			If KeyHit(KEY_F) Then App.ToggleFullscreen()							' Toggle fullscreen/window mode when user presses F.  (May need to disable this during user input.)
			If KeyHit(KEY_ESCAPE) Then End 
						
			'Last_Time_Delta      = Time_Delta									' Store timestep for this frame so we can reference it next frame.
			'Last_Time_Delta_Sec# = Time_Delta_Sec#

			' Smooth out framerate.
				
				If Not KeyDown(KEY_S)
				
					' Find the longest amount of time a frame took to render over the last few frames.	
								
						Max_FrameTime = 0
						For Frame = 0 To Frames-1
							If FrameTime[Frame] > Max_FrameTime Then Max_FrameTime = FrameTime[Frame]
						Next
					
					' Shift all times toward the end of the array by one to free up the first slot for a new time.
						
						For Frame = Frames-1 To 1 Step -1
							FrameTime[Frame] = FrameTime[Frame-1]
						Next					
					
					' Resize the array to have 1/8 as many elements as we are rendering frames per second.
					
						' The reason we do this is so that no matter what the framerate is, the system will adjust to big changes in framerate within 1/8
						' of a second.  The response time is only a concern so far as the system would render at a lower framerate for longer than it
						' really needs to.
					
						If Max_FrameTime > 0 Then Frames = Floor((1000.0 / Max_FrameTime) / 2.0)
						If Frames = 0 Then Frames = 1
										
						FrameTime = FrameTime[..Frames]						
					
					' Calculate how long this frame took to render.
						Time_Delta = MilliSecs()-System_Time
					
					' Add this frame's render time to the start of the array.
						FrameTime[0] = Time_Delta
				
					' Delay this frame to make it last as long as the longest in our array of frame times.
						
						If Max_FrameTime < 70
							While Time_Delta < Max_FrameTime
								Delay 0 
								Time_Delta = MilliSecs()-System_Time
							Wend
						EndIf
								
				EndIf

			' Draw framerate if user presses tab.
				If KeyDown(KEY_TAB) 
					FPS = 1000.0 / Float(Time_Delta)
					SetScale 1, 1
					DrawText FPS, 16, 16*1
					'DrawText "Sprites = "        + Sprite.SpriteList.Count(), 16, 16*2
					'DrawText "FruitSpawned   = " + Powerup.FruitSpawned,      16, 16*4
					'DrawText "FruitCollected = " + Powerup.FruitCollected,    16, 16*5
				EndIf

			' Flip new frame into view.
				Flip 0
					
		EndIf 
		
					
	Forever



' ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
' This type allows you to make games that can run at any resolution.
' ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Type ProjectionMatrix
	
	Global _Width%				' The size of the screen, in BlitzMax coordinates. 
	Global _Height%				' Normally BlitzMax coordinates correspond 1:1 with pixels on the screen, but when you adjust the projection matrix, that relationship changes.
	
	Global _VirtualWidth%		' The size of the visible region in which gameplay takes place.  The area inside the letterbox.
	Global _VirtualHeight%


	' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	' This function sets the scale of the projection matrix.
	'
	' If you simply wish your game to stretch vertically and horizontally to match the current resolution, and fill the screen, call this function with your desired "virtual" resolution.
	' Ie, if you want to build your game around an 800x600 resolution, then set Width and Height to 800,600.  If the game is then run at 1920x1200, it will be squashed vertically.
	'
	' If you want letterboxing however, call InitLetterbox() and then DrawLetterBox() every frame just before you flip.
	' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
		
		Function SetScale(Width%, Height%)
			
			_Width  = Width
			_Height = Height
			
			_VirtualWidth  = Width
			_VirtualHeight = Height
				
			?Win32

				Local D3D7Driver:TD3D7Max2DDriver = TD3D7Max2DDriver(_max2dDriver)
    
				If D3D7Driver
			
					Local Matrix#[] = [2.0/Width, 0.0, 0.0, 0.0,..
   		    	    			      0.0, -2.0/Height, 0.0, 0.0,..
       		    	      			  0.0, 0.0, 1.0, 0.0,..
           		    	  			  -1-(1.0/Width), 1+(1.0/Height), 1.0, 1.0]
    
				    D3D7Driver.device.SetTransform(D3DTS_PROJECTION, Matrix)

				Else
			? 
					' If on platform other than Win32, or using OpenGL run this code.
		
					glMatrixMode(GL_PROJECTION)
					glLoadIdentity()
    
					glortho(0, Width, Height, 0, 0, 1)
    
					glMatrixMode(GL_MODELVIEW)
					glLoadIdentity()
		
			?Win32

				EndIf
			?
		
		End Function


	' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	' This function initializes the letterbox.
	'
	' Call it with the virtual resolution you want to use for your game after you have set the graphics mode, and then DrawLetterBox() every frame just before you flip.
	'
	' These functions will automatically handle both letterboxing on screens which are too tall, and pillarboxing on screens which are too wide.  So if you design your game for 800x600,
	' then InitLetterbox() will squash things horizontally to maintain the proper aspect ratio, and DrawLetterbox() will add black bars to the sides of the display for you.
	'
	' 
	' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
		
		Function SetLetterbox(Width%, Height%)	

			Local NewWidth#, NewHeight#
						
			NewWidth#  = Width
			NewHeight# = Float(GraphicsHeight()) / (Float(GraphicsWidth()) / Float(Width))
		
			' If screen is wider than the desired apsect ratio...

				If NewHeight# < Height
				
					' Use pillarboxing instead of letterboxing.
										
						NewHeight# = Height
						NewWidth#  = Float(GraphicsWidth()) / (Float(GraphicsHeight())/Float(Height)) 	' Commenting this out will squash the game vertically on screens which are too wide.
																										' But without additional changes, black bars will still be drawn.						
				EndIf
			
			' Adjust the scale of the projection matrix to achieve the desired result.
				ProjectionMatrix.SetScale(NewWidth#, NewHeight#)
		
			' Store the size of the visible game region.
				_VirtualWidth  = Width
				_VirtualHeight = Height
	
		End Function 
		
		
	' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	' This function draws black bars over the portions of the screen which are outside the gameplay area.
	' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

		Function DrawLetterbox()
		
			Local Size%
			
			RenderState.Push()	
			
			If _VirtualHeight < _Height
				
				' Draw Letterbox.
				
					Size = (_Height-_VirtualHeight) / 2
				
					SetColor(0,0,0) 
							
					DrawRect(0,            0, _Width, Size)
					DrawRect(0, _Height-Size, _Width, Size)
					
			Else
				
				' Draw pillarbox.

					Size = (_Width-_VirtualWidth) / 2
				
					SetColor(0,0,0) 
							
					DrawRect(          0, 0, Size, _Height)
					DrawRect(_Width-Size, 0, Size, _Height)
				
			EndIf			
			
			RenderState.Pop() 	' Render push and pop simply resets the color and other display properties to whatever they were beforehand.  These two functions are in the code archives.
			
		End Function


	' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	' These functions return the virtual width and height of the usuable region of the screen, inside any letterboxing.
	'
	' Basically, these functions are equivalent to GraphicsWidth() and GraphicsHeight() when using a projection matrix where coordinates don't match up 1:1 to pixels
	' and/or letterboxing is being used.
	'
	' These functions will not return useful values until either ProjectionMatrix.SetScale() is called, or ProjectonMatrix.SetLetterbox() is called!
	' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

		Function Width#()
			Return _VirtualWidth
		End Function
		
		Function Height#()
			Return _VirtualHeight
		End Function
		
	
	' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
	' These functions tell you where the center of the screen is when using letterboxing.  
	'
	' Note that they do not calculate this using the width and height of the visible area of the screen, but rather, the size of the whole screen including the letterboxed regions.
	' This is important, because if you draw objects using the size of the visible region only, they will be higher on the screen than they should be, or more to the left.
	'
	' In my games, what I do is create a pivot called Origin, and place it in the center of the screen, and attach all my sprites to that, so the only time I need to worry about where
	' the center of the screen really is is when I position that pivot initially. 
	'
	' Then when I've done that, the top of the screen is at -ProjectionMatrix.Height#()/2, half the height I passed to SetLetterbox(), and so on.
	' -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
		
		Function CenterX#()
			Return _Width/2
		End Function
			
		Function CenterY#()
			Return _Height/2
		End Function
				
		
End Type
	
	

Const DEFAULT_IMAGE_FLAGS% = MIPMAPPEDIMAGE|FILTEREDIMAGE  ' BlitzMax defaults to MASKEDIMAGE|MIPMAPPEDIMAGE|FILTEREDIMAGE.

 
Type App

	Global Name$
	
	Global Width%
	Global Height%
	Global Depth%

	Global Window:TGadget
	Global Canvas:TGadget
	Global Panel:TGadget
	
	Global TG_FullScreen:TGraphics
	Global TG_Canvas:TGraphics
	
	Global Windowed%


	' -------------------------------------------------------------------------------------------------------------------------------------------------------
	' This function creates the game window, and sets up the graphics objects for windowed and fullscreen modes. 
	' -------------------------------------------------------------------------------------------------------------------------------------------------------

		Function Create(AppName$, AppWidth%, AppHeight%, AppDepth%=0, Fullscreen%=False, UseGL%=False)
	
			Local X%, Y%	
			
			' If we should use OpenGL on all platforms, then enable the openGL driver.
				If UseGL% Then SetGraphicsDriver GLMax2DDriver()
			
			' Warn programmer if the game is running in debug mode so they don't wonder why game is running choppy.
				DebugLog("WARNING: Game running debug mode - Performance will be reduced!")
									
			' Store application settings.
				Name$  = AppName$
				Width  = AppWidth
				Height = AppHeight	
				Depth  = AppDepth
				
			' If Depth is 0, try to find a suitable fullscreen bit depth.
			
				If Depth = 0
				
					If GraphicsModeExists(Width, Height, 16) Then Depth = 16
					If GraphicsModeExists(Width, Height, 24) Then Depth = 24
					If GraphicsModeExists(Width, Height, 32) Then Depth = 32
				
				EndIf		
					
			' Create a window in the center of the screen.
			' ClientWidth/Height is used because GadgetWidth/Height returns the entire width of the desktop in dual screen setups.
		
				X = ClientWidth(Desktop())/2  - Width/2
				Y = ClientHeight(Desktop())/2 - Height/2

				Window = CreateWindow(Name$, X, Y, Width, Height, Null, WINDOW_TITLEBAR|WINDOW_RESIZABLE|WINDOW_CLIENTCOORDS|WINDOW_HIDDEN)
				SetMinWindowSize(Window, GadgetWidth(Window), GadgetHeight(Window))
								
			' Create a panel in the window, drawn behind the canvas, which fills the empty space around the gameplay area when the window is maximized.
				
				Panel = CreatePanel(0, 0, Width, Height, Window)
				
					SetPanelColor(Panel, 0, 0, 0)
					SetGadgetLayout(Panel, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED)
							
			' Set game to windowed or fullscreen as desired.
				Select Fullscreen
					Case False SetWindowed()
					Case True  SetFullscreen()
				End Select
												
		End Function
		

	' -------------------------------------------------------------------------------------------------------------------------------------------------------
	' This function toggles between fullscreen or windowed mode, choosing the opposite of whichever is currently enabled.
	' -------------------------------------------------------------------------------------------------------------------------------------------------------
	
		Function ToggleFullscreen()
		
			Select Windowed
				Case False SetWindowed()
				Case True  If (Depth <> 0) Then SetFullscreen()
			End Select
			
		End Function

	' -------------------------------------------------------------------------------------------------------------------------------------------------------
	' This function puts the application in windowed mode.
	' -------------------------------------------------------------------------------------------------------------------------------------------------------
		
		Function SetWindowed()
		
			' End fullscreen mode if enabled.
				
				If TG_Fullscreen <> Null
					CloseGraphics TG_Fullscreen
					TG_Fullscreen = Null 
				EndIf	
			
			' Create a canvas.
											
				If Canvas = Null 
					Canvas    = CreateCanvas(ClientWidth(Window)/2-Width/2, ClientHeight(Window)/2-Height/2, Width, Height, Panel)
					TG_Canvas = CanvasGraphics(Canvas)
				EndIf	
																			
				If Canvas = Null    Then RuntimeError("Error in Application.SetWindowed() : Could not create canvas!")															
				If TG_Canvas = Null Then RuntimeError("Error in Application.SetWindowed() : Could not get canvas graphics context!")
				
				SetGraphics TG_Canvas
				
				ShowGadget Window
				ActivateGadget Canvas
			
			' Record that windowed mode is enabled.
				Windowed = True
							
			' Canvas must be activated for input or else game will make user click on canvas before any polled keyboard input is returned.
				EnablePolledInput()			
			
			' Show mouse if mouse is currently supposed to be visible.
				If MouseVisible Then ShowMouse(True)					
			
			' Set the blending mode to alpha.
				SetBlend(ALPHABLEND)
				
			' Set mask color to magenta so black pixels are not made transparent when images without an alpha mask are loaded.
				SetMaskColor(255, 0, 255)

			' Set midhandle so images are loaded properly.
				AutoMidHandle True
			
			' Set image flags.
				AutoImageFlags(DEFAULT_IMAGE_FLAGS)
								
			' Buffer sprite images in video memory.	
			'	Sprite.BufferImages()									

			' Scale the graphics onscreen and display them letterboxed if needed.
				ProjectionMatrix.SetLetterBox(800, 500)
				
		End Function


	' -------------------------------------------------------------------------------------------------------------------------------------------------------
	' This method sets the application to fullscreen mode, unless no fullscreen mode in the desired resolution exists.
	' -------------------------------------------------------------------------------------------------------------------------------------------------------

		Function SetFullscreen()
			
			' If no fullscreen mode is available, set windowed mode instead.
				If Depth = 0
					DebugLog("Error in Application.SetFullscreen() : Depth = 0.  Could not set full screen mode!") 
					SetWindowed()
					Return
				EndIf
			
			' Hide window, free canvas.			
				HideGadget Window
				
				If Canvas <> Null 

					'CloseGraphics(TG_Canvas) 
																		
					FreeGadget Canvas
					
					Canvas    = Null
					TG_Canvas = Null
										
				EndIf
														
			' Set drawing operations to fullscreen.
				If TG_Fullscreen = Null Then TG_Fullscreen = Graphics(Width, Height, Depth)
				
			' If the attempt to set a fullscreen mode fails, put us back in windowed mode. 
				If TG_Fullscreen = Null 
					DebugLog("Error in Application.SetFullscreen() : TG_Fullscreen = Null.  Could not set full screen mode!") 
					SetWindowed()
					Return
				EndIf

			' Record that fullscreen is enabled.
				Windowed = False

			' Show mouse if mouse is currently supposed to be visible.
				If MouseVisible Then ShowMouse(True)
				
			' Set the blending mode to alpha.		
				SetBlend(ALPHABLEND)

			' Set mask color to magenta so black pixels are not made transparent when images without an alpha mask are loaded.
				SetMaskColor(255, 0, 255)
				
			' Set midhandle so images are loaded properly.
				AutoMidHandle True

			' Set image flags.
				AutoImageFlags(DEFAULT_IMAGE_FLAGS) 
				
			' Buffer sprite images in video memory.	
			'	Sprite.BufferImages()									

			' Scale the graphics onscreen and display them letterboxed if needed.
				ProjectionMatrix.SetLetterBox(800, 500)
																		
		End Function

				
End Type						


' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' These functions override the regular image loading functions so that we can display an error when an image is missing. 
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

	Function LoadImage:TImage(Url:Object, Flags%=-1, ReturnNull%=False)
	
		Local Image:TImage
					
		Image = Brl.Max2D.LoadImage(Url, Flags)
		
		If Image = Null 
			If ReturnNull  
				Return Null
			Else	
				RuntimeError("The following image failed to load: '" + String(Url) + "'.  Please reinstall the game.")
			EndIf
		EndIf
		
		' Buffer image in video ram.
			DrawImage Image, App.Width, App.Height
		
		'LoadScreen.Update(Url)
		
		Return Image
		
	End Function
	

	Function LoadAnimImage:TImage(Url:Object, Cell_Width%, Cell_Height%, First_Cell%, Cell_Count%, Flags%=-1, ReturnNull%=False)
	
		Local Image:TImage
		Local Frame%

		Image = Brl.Max2D.LoadAnimImage(Url, Cell_Width, Cell_Height, First_Cell, Cell_Count, Flags)
		
		If Image = Null 
			If ReturnNull  
				Return Null
			Else	
				RuntimeError("The following image failed to load: '" + String(Url) + "'.  Please reinstall the game.")
			EndIf
		EndIf
		
		' Buffer image in video ram.
			For Frame = First_Cell To First_Cell+(Cell_Count-1)
				DrawImage Image, App.Width, App.Height, Frame
			Next  
		
		'LoadScreen.Update(Url)
		
		Return Image
		
	End Function


	Function LoadPixmap:TPixmap(Url:Object, ReturnNull%=False)
	
		Local Pixmap:TPixmap
					
		Pixmap = Brl.Pixmap.LoadPixmap(Url)
		
		If Pixmap = Null 
			If ReturnNull  
				Return Null
			Else	
				RuntimeError("The following image failed to load: '" + String(Url) + "'.  Please reinstall the game.")
			EndIf
		EndIf
		
		'LoadScreen.Update(Url)
		
		Return Pixmap
		
	End Function		


' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' This function overrides the standard RuntimeError function which does not work properly.  (Assert also does not work.)
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

	Function RuntimeError(Error$)
		EndGraphics
		DebugLog(Error$)
		Notify(Error$, True)
		End
	End Function
	
	
' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' This function oveerides the standard Flip() function with a lag fix for DirectX.
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

	' No longer needed in latest version of BlitzMax.

	'Function Flip(Sync%=-1)
		
		'Brl.Graphics.Flip Sync
		
		'?Win32
		'	If TD3D7Max2DDriver(_max2dDriver)
		'		Local sdesc:DDSurfaceDesc2 = New DDSurfaceDesc2
		'		sdesc.dwSize = SizeOf(sdesc)
		'		Local res:Int = PrimaryDevice.backbuffer.Lock(Null,sdesc,DDLOCK_WAIT|DDLOCK_READONLY,Null)
		'		PrimaryDevice.backbuffer.unlock(Null)
		'	EndIf
		'?
		
	'End Function


' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' These functions override the standard mouse visibility functions so that we can keep track of the mouse visible state.
'
' For ShowMouse:
'
' If Force% is False, then the mouse will not be shown if the current state indicates it is visible.  This is to avoid mouse flicker which is caused by
' showing the mouse over and over.
'
' If Force% is True, the mouse is shown regardless of what state MouseVisible indicates it is in.  This is used during fullscreen/window mode switches where
' the mouse is hidden by the system automatically.
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

	Global MouseDown_Left%, MouseDown_Right%, MouseDown_Middle%
	Global MouseHit_Left%, MouseHit_Right%, MouseHit_Middle%
	Global Mouse_X#, Mouse_Y#
	Global Old_Mouse_X# = MouseX()
	Global Old_Mouse_Y# = MouseY()
	Global Mouse_Speed_X#, Mouse_Speed_Y#
	Global MouseVisible% = True
	Global Mouse_ForceRecenter% 


	Function ShowMouse(Force%=False)
		If (MouseVisible = False) Or (Force = True)
			MouseVisible = True
			Brl.System.ShowMouse()
		EndIf
	End Function

	
	Function HideMouse()
		MouseVisible = False
		Brl.System.HideMouse()	
	End Function
	
	
	Function AutoRecenterMouse(Recenter%=False) 
		
		Mouse_ForceRecenter = Recenter
		
		Select Recenter
		
			Case True  
				HideMouse()
				MoveMouse App.Width/2, App.Height/2
				
			Case False 
				ShowMouse()
			
		End Select
		
	End Function
	
	
' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' This function gets the mouse input for this frame.
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

	Function UpdateMouse()								
		
		Const SAFEZONE_RADIUS# = 100		
				
		Mouse_X# = MouseX()
		Mouse_Y# = MouseY()
			
		Mouse_Speed_X# = Mouse_X# - Old_Mouse_X#
		Mouse_Speed_Y# = Mouse_Y# - Old_Mouse_Y#

		MouseDown_Left   = MouseDown(1)
		MouseDown_Right  = MouseDown(2)
		MouseDown_Middle = MouseDown(3)	
				
		MouseHit_Left    = MouseHit(1)
		MouseHit_Right   = MouseHit(2)
		MouseHit_Middle  = MouseHit(3)
		
		' Recenter mouse if desired.
		' Recentering the mouse allows Mouse_Speed to work consistently.

			If Mouse_ForceRecenter 
				
				If (Abs(App.Width/2 - Mouse_X#) > SAFEZONE_RADIUS#) Or (Abs(App.Height/2 - Mouse_Y#) > SAFEZONE_RADIUS#)
			
					MoveMouse App.Width/2, App.Height/2
				
					Old_Mouse_X# = App.Width/2  - Mouse_Speed_X#
					Old_Mouse_Y# = App.Height/2 - Mouse_Speed_Y#
					
				Else
				
					Old_Mouse_X# = Mouse_X#
					Old_Mouse_Y# = Mouse_Y#
									
				EndIf			
				
			EndIf
	
	End Function


' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' This function checks for events in the event queue and acts upon them.
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

	Function EventHandler()

		MouseHit_Left   = False
		MouseHit_Right  = False
		MouseHit_Middle = False

		While PollEvent() <> 0
		
			'DebugLog("EventID: " + EventID())
			'If Scoreboard.TEXT_AngerMeter <> Null 
			'	If EventID() <= 258 Then Scoreboard.TEXT_AngerMeter.Set(EventID()) 
			'EndIf
			
			Select EventID()
					
				Case EVENT_APPSUSPEND 		' Application suspended. Triggered when window is minimized.
					
					' Pause music.
'						If Sound.MusicChannel <> Null Then Sound.MusicChannel.SetPaused(True)
				
				
				Case EVENT_APPRESUME  		' Application resumed.
				
					' Resume music.
'						If Sound.MusicChannel <> Null Then Sound.MusicChannel.SetPaused(False)
				
				 
				Case EVENT_APPTERMINATE 	' Application wants to terminate. 
				Case EVENT_KEYDOWN 			' Key pressed. Event data contains keycode. 
				Case EVENT_KEYUP 			' Key released. Event data contains keycode. 
				Case EVENT_KEYCHAR 			' Key character. Event data contains unicode value. 
				
				Case EVENT_MOUSEDOWN 		' Mouse button pressed. Event data contains mouse button code.
				
					Select EventData()
					
						Case 1 
							MouseDown_Left   = True
							MouseHit_Left    = True
							
						Case 2 
							MouseDown_Right  = True
							MouseHit_Right   = True
							
						Case 3 
							MouseDown_Middle = True
							MouseHit_Right   = True
							
					End Select
					
					
				Case EVENT_MOUSEUP 			' Mouse button released. Event data contains mouse button code. 
				
					Select EventData()
						Case 1 	MouseDown_Left   = False
						Case 2 	MouseDown_Right  = False
						Case 3 	MouseDown_Middle = False
					End Select
				
				
				Case EVENT_MOUSEMOVE 		' Mouse moved. Event x and y contain mouse coordinates.
				
					Mouse_X = EventX()
					Mouse_Y = EventY()
				
						 
				Case EVENT_MOUSEWHEEL 		' Mouse wheel spun. Event data contains delta clicks. 
				Case EVENT_MOUSEENTER 		' Mouse entered gadget area. 
				Case EVENT_MOUSELEAVE 		' Mouse left gadget area. 
				Case EVENT_TIMERTICK 		' Timer ticked. Event source contains timer object. 
				Case EVENT_HOTKEYHIT 		' Hot key hit. Event data and mods contains hotkey keycode and modifier.
				Case EVENT_MENUACTION 		' Menu has been selected. 
				Case EVENT_WINDOWMOVE 		' Window has been moved. 
				Case EVENT_WINDOWSIZE 		' Window has been resized.
				 
				Case EVENT_WINDOWCLOSE 		' Window close icon clicked. 
					End
					
				Case EVENT_WINDOWACTIVATE	' Window activated. 
				Case EVENT_WINDOWACCEPT 	' Drag and drop operation was attempted. 
				Case EVENT_GADGETACTION 	' Gadget state has been updated. 
				Case EVENT_GADGETPAINT 		' A canvas gadget needs to be redrawn. 
				Case EVENT_GADGETSELECT		' A treeview node has been selected. 
				Case EVENT_GADGETMENU 		' User has right clicked a treeview node or textarea gadget. 
				Case EVENT_GADGETOPEN 		' A treeview node has been expanded. 
				Case EVENT_GADGETCLOSE 		' A treeview node has been collapsed. 
				Case EVENT_GADGETDONE 		' An HTMLview has completed loading a page. 

			End Select

		Wend

	End Function


' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' This hooks the gadget paint event so it can redraw the canvas as needed while another window is dragged over the game window.
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

		
	AddHook EmitEventHook, MyHook	
		
	Function MyHook:Object(iId:Int, tData:Object, tContext:Object)
	
 		Local Event:TEvent=TEvent(tData)
		
		If App.Canvas <> Null
			If (Event.Source = App.Canvas) And (Event.ID = EVENT_GADGETPAINT)
				Flip		
				Return Null
			EndIf	
		EndIf

		Return tData
		
	End Function





Type RenderState


	Global RenderStateList:TList = CreateList()
				
	
	Field Alpha#
	Field Blend%
	Field ClsColor_R%, ClsColor_G%, ClsColor_B%
	Field Color_R%, Color_G%, Color_B%
	Field Handle_X#, Handle_Y#
	Field ImageFont:TImageFont
	Field LineWidth#
	Field MaskColor_R%, MaskColor_G%, MaskColor_B%
	Field Origin_X#, Origin_Y#
	Field Rotation#
	Field Scale_X#, Scale_Y#
	Field Viewport_X%, Viewport_Y%, Viewport_Width%, Viewport_Height%


	' -------------------------------------------------------------------------------------------------------------------------------------------------------
	' These methods allow you to save and restore the current render settings
	'
	' Each time you call the push method, the current state is placed on the stack.
	' Each time you call the pop method, the last state placed on the stack is restored and removed from the stack.
	' -------------------------------------------------------------------------------------------------------------------------------------------------------

		
		Function Push()

			Local RS:RenderState = New RenderState

			RS.Alpha# = GetAlpha#()
			RS.Blend  = GetBlend()
			GetClsColor(RS.ClsColor_R, RS.ClsColor_G, RS.ClsColor_B)
			GetColor(RS.Color_R, RS.Color_G, RS.Color_B) 
			GetHandle(RS.Handle_X#, RS.Handle_Y#)
			RS.ImageFont = GetImageFont()
			RS.LineWidth# = GetLineWidth#()
			GetMaskColor(RS.MaskColor_R, RS.MaskColor_G, RS.MaskColor_B)
			GetOrigin(RS.Origin_X#, RS.Origin_Y#)
			RS.Rotation# = GetRotation#()
			GetScale(RS.Scale_X#, RS.Scale_Y#)
			GetViewport(RS.Viewport_X, RS.Viewport_Y, RS.Viewport_Width, RS.Viewport_Height)
		
			RenderStateList.AddLast(RS)
		
		End Function		


		Function Pop()
		
			Local RS:RenderState = RenderState(RenderStateList.RemoveLast())	
				
			SetAlpha(RS.Alpha#)
			SetBlend(RS.Blend)
			SetClsColor(RS.ClsColor_R, RS.ClsColor_G, RS.ClsColor_B)
			SetColor(RS.Color_R, RS.Color_G, RS.Color_B) 
			SetHandle(RS.Handle_X#, RS.Handle_Y#)
			SetImageFont(RS.ImageFont)
			SetLineWidth(RS.LineWidth#)
			SetMaskColor(RS.MaskColor_R, RS.MaskColor_G, RS.MaskColor_B)
			SetOrigin(RS.Origin_X#, RS.Origin_Y#)
			SetRotation(RS.Rotation#)
			SetScale(RS.Scale_X#, RS.Scale_Y#)
			SetViewport(RS.Viewport_X, RS.Viewport_Y, RS.Viewport_Width, RS.Viewport_Height)

		End Function


End Type



The delay happens when you hit ESC which just calls "End", or when you switch from windowed to fullscreen for the first time, in which case it occurs on the "FreeGadget Canvas" line in the Fullscreen() function.

I wonder where it breaks when I switch from fullscreen to windowed for the first time... cause it wouldn't be there, that's for sure.

[edit]

Yep, when switching from fullscreen to windowed, the delay occurs on the "CloseGraphics TG_Fullscreen" line in the SetWindowed() function.

And presumably "End" calls an internal function to shut down the current graphics context, so in all cases it's most likely shutting down the graphics the first time which is causing the delay.

Subsequent shutdowns however, have no delay. So pressing ESC after switching fullscreen to windowed results in no delay because there was a delay when making the switch.

I'll take a peek at this later.. but I just wanted to say, your sig takes up half of my screen.

Your screen is too little then. :-)

I also get a long delay on exit, maybe 5 secs.

Game seems fine, but I'd really like to see more "game" than this. Look forward to it. Hope you get it done.

I noticed that the scores that fly up to the score at the top don't move that smoothly (nor do some fast moving aliens). Are you using Int coords? Or is your timing code a tiny bit jerky? Anyone else see this? Other things are smooth on my PC.

It's annoying when the alien's spawn right under you. I guess this will change but it would have been nice to have had a "safe zone" around the player which cannot be spawned into.

Try holding down the S key and tell me if that makes a difference for you in the smoothness.

It's annoying when the alien's spawn right under you. I guess this will change but it would have been nice to have had a "safe zone" around the player which cannot be spawned into.



Which aliens are you referring to exactly? I don't think the purple ameoba aliens spawn at the bottom of the screen, and the ghosts will never spawn within a certain radius of your ship.

The ameobas will move off the bottom of the screen and then reappear there, but that's all I can think of which you could be referring to.

Sorry I've deleted it now and emptied my recycle bin so can't check (download was slow). It just felt quite a few times like an alien appeared right next to me and I crashed into it. Perhaps it's because they fade in and I was moving fast and it's not that obvious where they are appearing (no "flash" beforehand or anything).

What does the S Key do?

What resolution is your desktop set to? Do you have multiple monitors with the desktop spanned across them?
2560x1600. no, just one.

"What does the S Key do?"

It disables the framerate averaging code and simply draws the frames as quickly as it can.

Dmaz:
http://blitzmax.com/Community/posts.php?topic=70985

Looks like they never fixed that issue. Try setting your desktop to 1920x1200 and I bet it works.

My app creates a window and a panel when it starts up. The panel makes a black background around the central drawing region when you maximize the window.

yeah, it seems that if I lower my desktop resolution I can run this. so this is a panel in maxgui?

Yes, I use MaxGUI.

I create a window, and in that window I place a black panel which is set to resize with the window, and then in the center of that panel I place a canvas which does not resize with the window. That way, when you maximize the window, you get a black background around the gameplay area.

I guess I should just get rid of the panel, and not allow the user to maximize the window, since if they haven't fixed this issue since they were first informed of it a year ago, it's probably not gonna get fixed anytime soon.

Also there's a slight possiblity it may fix the freeze when you exit the game.

do you have the latest MaxGui from the svn repository?

I'm not sure why the framerate seems sluggish on my system, there is slowdown with very few enemies. Not sure how efficient your code is or what you're doing behind the scenes.

My code's efficient. I'm not doing anything particularly taxing on the system.

It's probably just the fact that it's drawing hundreds of little stars. BlitzMax has the same slowdown issues when drawing lots of images that Blitz3D has when you try to render hundreds of particles.

Also stuff can look choppier on an LCD when it's a small object moving on a dark background than when the whole screen is bright and changing. Try pressing TAB and it will tell you the framerate. And try holding down S to see if my framerate smoothing code is somehow the cause. That disables it.

do you have the latest MaxGui from the svn repository?


What SVN repository?

no problems on running or closing


Looks good, like the graphics style, apart from the ship banking its hard to see any difference, maybe make the wing that turns away a little darker and the other lighter

On the weapons maybe make the missiles use the right mouse, fire left
Gives the user a bit more to do other than just keeping the left mouse down

Great sound when you get a power up

Don’t know what you’ve got for other levels, but what about a big mother ship/beetle moving right to left at top of screen, something else to shoot at while dodging the others

What SVN repository?

http://www.blitzmax.com/Community/posts.php?topic=76731

"It uses the same video mode as your desktop is set to."

Won't run, just exits, and worse...there is nothing you can do about it. At least that anyone has come up with.

See this thread:

http://www.blitzbasic.com/Community/posts.php?topic=80208

I get that delay when I close the application, but no problems, otherwise. The moving starfield on some levels is a nice touch, and I think you should have more going on in the backgrounds of the levels. However, I think the stars should move a bit more slowly. The current scroll speed makes the effect a tad harsh.

What's the latest version of the sprite system? I'm thinking of dusting off my programming fingers, and I want to have everything up to date.

SpaceAce

Nice one swifty. Fairly enjoyable. More enemies on screen at the one time, and big motherships!

What's the latest version of the sprite system? I'm thinking of dusting off my programming fingers, and I want to have everything up to date.

I believe you'll need to contact SSwift via email. I think he's serving a ban right now.

That is correct. I don't know if it's permanent or temporary.

I believe you'll need to contact SSwift via email. I think he's serving a ban right now.


That is correct. I don't know if it's permanent or temporary.


Oh, wow, I had no idea. Thanks for the heads-up.

SpaceAce

Downloading to test now. Will report back...

graphics and everything are nice but it needs more stucture (ie levels). Just playing for ages till you die will get boring quickly.

I noticed the choppy movements too. It should be like liquid smooth sprite movement IMO.

Overall, it looks cool but yeah, needs more structured encounters.