my idea was to tie them up to a common method call since they dont extend the same ship class, but im not sure if i even need it right now. no biggie. ill look for an alternate route. still good info none the less thanks
In that case you don't extend the ship class, but create a base class that both the player and the enemy can inherit from that contains common variables and methods.
Here's a bit of a complex example, where classes use chain inheritance.
[CODE lang="cerberus" title="example.cxs"]Strict
Import mojo
Const ALIEN_TYPE:= 1
' CPoint is the base class for any 2D pixel coordinate
' Access will be via property setters and getters.
Class CPoint
Field x:Float
Field y:Float
' Assign a 2D coordinate on construction
Method New( x:Float, y:Float )
Self.x = x
Self.y = y
End Method
' The setters and getters for the X coordinate
Method X:Void( x:Float ) Property
Self.x = x
End Method
Method X:Float() Property
Return Self.x
End Method
' The setters and getters for the Y coordinate
Method Y:Void( y:Float ) Property
Self.y = y
End Method
Method Y:Float() Property
Return Self.y
End Method
End Class
' CRect is the base class for a 2D rectangle. This will also be the bounding collision box.
Class CRect Extends CPoint
' The width and height will also be stored as a point object, though it would be better here
' if the CPoint values were of an integer value and not floats as defined.
Field dimensions:CPoint
' Two ways to define the rectangle. The first passing all the dimentions. The second just with the Width and the Height.
Method New( x:Int, y:Int, w:Int, h:Int )
Super.New( x, y )
Self.dimensions = New CPoint( w, h )
End Method
Method New( w:Int, h:Int )
Self.dimensions = New CPoint( w, h )
End Method
' The width and the height need to be easily accessible to make adjustments, so these will be done via setter and getter properties
Method Width:Void( w:Int ) Property
Self.dimensions.X = w
End Method
Method Height:Void( h:Int ) Property
Self.dimensions.Y = h
End Method
Method Width:Int() Property
Return dimensions.X
End Method
Method Height:Int() Property
Return dimensions.Y
End Method
End Class
' The sprite class extends CRect and CSprite will be the base class for all other movable object blocks.
' All sprite related things can be implemented here.
' For this example eleven core member fields are implemented.
Class CSprite Extends CRect
Field id:Int ' An integer to identify the sprite
Field type:Int ' An integer to identify the type of sprite. You would use this to check before casting to the appropriate object type.
Field img:Image ' A variable to hold the current image set to use.
Field img1:Image ' Reference to one image set. This is the main sprite image
Field img2:Image ' Reference to another image set. This one will be the explosion.
Field frame:Int ' Keep track of the current animation frame.
Field totalframes:Int ' Keep track of the total number of frames for the full animation sequence.
Field flags:Int ' Binary data flags to keep track of the sprites state.
Field delay:Float ' Simple delay count between each animated frame
Field vx:Float ' Variable to store the vector for the X axis movement
Field vy:Float ' Variable to store the vector for the Y axis movement
Const DRAW_IMAGE2:= $01 ' Constant binary data flag for easy reading.
' To keep it simple, just use the two image strips for this job.
' A more complex version should be used for full blown sprite sheets.
Method New( id:Int, x:Float, y:Float, img1:Image, img2:Image = Null )
Super.New( x, y, 1, 1 ) ' Initialise the base Rectangle. The width and the height will be set when the images are assigned.
Self.id = id ' Set the id for the sprite
' Assign the image sets. NOTE: The first image will set the bounding rectangle.
' And the second image will only be applied if there is one. It will not adjust the bounding rectangle.
' For two versions of a bounding rectangle; a different approach is needed.
Self.AssignImage1( img1 )
If img2<>Null Self.AssignImage2( img2 )
End Method
' A secondary constructor that doesn't assign any images
Method New( id:Int, x:Float, y:Float )
Super.New( x, y, 1, 1 )
Self.id = id
End Method
' Set the direction vectors to move the sprite.
Method SetVel:Void( vx:Float, vy:Float )
Self.vx = vx
Self.vy = vy
End Method
Method AssignImage1:Void( img:Image )
Self.img1 = img
Self.Width = img.Width()
Self.Height = img.Height()
End Method
Method AssignImage2:Void( img:Image )
Self.img2 = img
End Method
Method Id:Int()
Return id
End Method
' Methods to flip the direction vectors
Method FlipVX:Void()
Self.vx *= -1
End Method
Method FlipVY:Void()
Self.vy *= -1
End Method
' Returns the actual sprite base data.
' To make any use of it, you would have to cast it up to the derived child object.
' This is where the type field comes into play.
' NOTE: Always check for a Null or Non Null object before doing any actions.
' And only cast when absolutely necessary to avoid performance penalties.
Method IsHit:CSprite()
If Self.flags & DRAW_IMAGE2 Return Self
Return Null
End Method
' This method is used to change the image set depending on the flag value.
Method SwitchImageSet:Void()
If img1 = Null Return ' Safety check to avoid memory exceptions.
Self.img = img1
If (Self.flags & DRAW_IMAGE2) And img2<>Null Self.img = img2 ' Switch to the second images set if the flag is set.
Self.totalframes = img.Frames() - 1 ' IMPORTANT: The second set could have a different number of animation frames. So make adjustments.
End Method
' The method to render the sprite image to screen
Method Draw:Void()
If Self.img = Null Return ' Safety check to avoid memory exceptions
DrawImage( img, Self.X, Self.Y, Self.frame ) ' Display the actual sprite image frame.
DrawText( Self.Id(), Self.x, Self.Y ) ' Display the id number given to a sprite.
End
End Class
' All the aliens are going to be stored onto a stack container. The stack it's self will be static to allow access through calling static functions.
' Doing it this ways makes it much easier to search and manipulate objects items without.
' There is nothing to from creating a common CSprite list, but you would have to identify the required type and cast the object accordingly.
Class CAlien Extends CSprite
' As there will be a number of aliens, then make a static stack of the alien type, so it can be accessed form anywhere.
Global aliens:Stack<CAlien> = New Stack<CAlien>
' The basic constructor just passing the id and the position
Method New( id:Int, x:Float, y:Float )
Super.New( id, x, y )
Self.type = ALIEN_TYPE
End Method
' A method to set the current object instance directional speeds.
' If the speeds need changing after; then a function (not a method) will be needed to find the sprite and update.
Method SetSpeeds:Void( vx:Float, vy:Float )
Self.vx = vx
Self.vy = vy
End Method
' These functions can be accessed anywhere without the need to keep track of each alien object instance.
' Add an alien to the stack container, but return the alien object created so addition operations can be carried out if needed.
Function Add:CAlien( id:Int, x:Float=0, y:Float=0)
Local alien:= New CAlien( id, x, y )
aliens.Push( alien )
Return alien
End Function
Function AssignImages:Void( alien:CAlien, img1:Image, img2:Image = Null )
alien.AssignImage1( img1 )
If img2<>Null alien.AssignImage2( img2 )
End Function
' Routine to update a number of things related to the aliens on screen.
Function UpdateAliens:Void()
For Local i:=Eachin aliens
' Flip the direction the alien sprite is moving if the edge of the screen is reached.
If i.X < 0 Or i.X > (DeviceWidth()-32) i.FlipVX()
If i.Y < 0 Or i.Y > (DeviceHeight()-32) i.FlipVY()
i.X += i.vx
i.Y += i.vy
' Very simple frame delay
If i.delay > 20
i.delay = 0
i.frame +=1
If i.frame > i.totalframes i.frame = 0
Endif
i.delay += 1
' Internal routine to set the collision state for each of the aliens in the list
i.flags &= ~CSprite.DRAW_IMAGE2 ' Always clear the current collision before proceeding.
' Loop though the aliens
For Local j:=Eachin aliens
If i.Id() = j.Id() Continue ' Skip the one current testing against.
' NOTE: Though the objects are of type CAlien, they are children of CSprite and grand children of CRect.
' So the compiler can do automatic casting to a CRect object, which is what the Rect2Rect function excepts.
If Rect2Rect( j, i )
i.flags |= CSprite.DRAW_IMAGE2
j.flags |= CSprite.DRAW_IMAGE2
Endif
Next
' This needs to be called after to switch the image set based on the collision information set internally
i.SwitchImageSet()
Next
End Function
End Class
Class CGame Extends App
' NOTE: Images themselves can be stored in a Stack of Images. You just have to keep track of them i.e. via an asset manager.
Field alienImage:Image
Field bangImage:Image
Method OnCreate:Int()
' Load the images to use
alienImage = LoadImage( "alien.png", 32, 32, 4 )
bangImage = LoadImage( "bang.png", 32, 32, 4 )
' Create 10 aliens
For Local i:Int = 1 To 10
Local alien:CAlien = CAlien.Add( i, Rnd(DeviceWidth()-32), Rnd(DeviceHeight()-32) )
CAlien.AssignImages( alien, alienImage, bangImage )
alien.SetVel( Rnd(-2, 2), Rnd(-2, 2) )
Next
Return 0
End Method
Method OnUpdate:Int()
CAlien.UpdateAliens()
Return 0
End Method
Method OnRender:Int()
Cls
For Local i:=Eachin CAlien.aliens
i.Draw()
' If an object is returned, then draw the message.
If i.IsHit() DrawText( "OUCH", i.X, i.Y+21 )
Next
Return 0
End Method
End Class
Function Rect2Rect:Bool( r1:CRect, r2:CRect )
Return (r1.X + r1.Width) >= r2.X And r1.X <= (r2.X + r2.Width) And (r1.Y + r1.Height) >= r2.Y And r1.Y <= (r2.Y + r2.Height)
End Function
Function Main:Int()
New CGame()
Return 0
End Function
[/CODE]
Play around with this code and images.
As an exercise, break it up into separate files, make certain parts private, add a player, bullets, scorings and a common list to render all sprite objects.