Android Tutorial How to make games

Informatix

Expert
Licensed User
Longtime User
I couldn't set up a multi-touch handler in my Accelerated Surface.
In fact, you can. The Touch event of AcSf returns an event object that you can pass to the GestureDetector library to get all touch details or, better, you can bind a GestureDetector instance to the AcSf.

Do you know better learning resources to start with?
There are plenty. For example:
http://www.rengelbert.com/tutorial.php?id=176
http://theinvader360.blogspot.fr/2013/05/street-race-swipe-libgdx-scene2d.html
http://steigert.blogspot.fr/2012/06/12-libgdx-tutorial-2d-animations.html

Yes, it's a dead project and I've never been able to make it work properly, so I should remove it definitely from the suggested game engines.

So, by now, I'm trying GameSprite that could work, but will I find it not suitable to me like Accelerated Surface?
If you find AcSf too limited, then GameSprite is even more limited (and slower).

To make games, my advice is to use libGDX. Especially if you want to make a Civilization-like game that requires a tile system. The learning curve is not as steep as you think.
 

Informatix

Expert
Licensed User
Longtime User
Extra: You must be really comfortable with high-school level mathematics. Without being familiar with vectors and trigonometry, you'll have a really hard time building your own game, no matter which platform.
It depends on the kind of games of course, but I agree that, without basic math skills, doing games can become quickly a complicated task.
 

StefanoAccorsi

Member
Licensed User
Longtime User
Thank you so much Informatix and wonder. I'm trying but without success. For example, I'm following the gamefromscratch tutorial on Scene2D but it doesn't work. I created a simple class for the actor:

B4X:
Sub Class_Globals
    Dim MyActor As lgScn2DActor
    Private Texture As lgTexture
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
    'Initializes the actor
    Texture.Initialize("sprites/mario.png")
    MyActor.Initialize("Mario")
    MyActor.Name="Mario"
End Sub

public Sub MyActor_Draw(batch As lgSpriteBatch, alpha As Float)
    batch.DrawTex(Texture, 20%x, 20%y)
End Sub

and used it in the main:

B4X:
Sub Globals
    Dim lGdx As LibGDX
    Dim GL As lgGL
    Dim Stage As lgScn2DStage
    Dim Mario As Actor
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Initializes libGDX
    lGdx.Initialize("LG")
End Sub

Sub Activity_Resume
    'Informs libGDX of Resume events
    If lGdx.IsInitialized Then lGdx.Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
    'Informs libGDX of Pause events
    If lGdx.IsInitialized Then lGdx.Pause
End Sub

Sub LG_Create   
    'Initializes the stage
    Stage.Initialize2(lGdx.Graphics.Width, lGdx.Graphics.Height, True, "ST")
   
    'Initialize the actor in the dedicated class
    Mario.Initialize(lGdx)
   
    Stage.AddActor(Mario.MyActor)
End Sub

Sub LG_Resize(Width As Int, Height As Int)
    'Sets the stage viewport
    Stage.SetViewport(Width, Height, True)
End Sub

Sub LG_Render
    'Clears the screen
    GL.glClearColor(0, 0, 0, 1)
    GL.glClear(GL.GL10_COLOR_BUFFER_BIT)

    'Draws the actors
    Stage.Draw
End Sub

Sub LG_Pause
End Sub

Sub LG_Resume
End Sub

Sub LG_Dispose
    'Disposes all resources
    Stage.dispose
End Sub

It works without any error but nothing is shown on the screen ... mario.png is a simple "Mario bros" file found on internet.

What's wrong with it? It seemed so simple ...
 

Informatix

Expert
Licensed User
Longtime User
You don't load an image, so the result is not very surprising. Anyway, you should not begin with Scene2D, but with the basic things: you load a texture, you create a sprite or a texture region from it and you display that in a SpriteBatch. Don't skip the tutorial pages too quickly. Start here: http://www.gamefromscratch.com/post/2013/10/02/LibGDX-Tutorial-3-Basic-graphics.aspx
 

StefanoAccorsi

Member
Licensed User
Longtime User
The original was:

B4X:
public class MyActor extends Actor {
   Texture texture = new Texture(Gdx.files.internal("data/jet.png"));
   @Override
   public void draw(Batch batch, float alpha){
      batch.draw(texture,0,0);
   }
}

So I supposed that:

B4X:
Public Sub Initialize
    'Initializes the actor
    Texture.Initialize("sprites/mario.png")
    MyActor.Initialize("Mario")
    MyActor.Name="Mario"
End Sub

public Sub MyActor_Draw(batch As lgSpriteBatch, alpha As Float)
    batch.DrawTex(Texture, 0, 0)
End Sub

was a good translation ...

Anyway, as I wrote in the first post I started from the beginning. The "Hello world" tutorial was easy, and so were the next two but I got stuck in the 3b one (TextureAtlas and Animation). As I wrote I can't translate it, same error I obviously made with the previous example.
In this one the problem seems to lie in this line:
B4X:
textureAtlas = new TextureAtlas(Gdx.files.internal("data/spritesheet.atlas"));
animation = new Animation(1/15f, textureAtlas.getRegions());
that I translated with:
B4X:
...
atlas.InitializeWithFile2(lGdx.Files.internal("atlas/spritesheet.atlas"))
animation.Initialize((1.0/15.0), atlas.GetAllRegions)
...
but a List<Object> (returned by atlas.GetAllRegions) can't be casted to an array of lgTextureRegion. I transformed the list in an array but the program crashes at runtime.

But, since about the example at top you wrote that I didn't load any image, while I supposed to load it with the line
B4X:
Texture.Initialize("sprites/mario.png")
then probably I made a similar mistake here that, anyway, I still can't find...
 

wonder

Expert
Licensed User
Longtime User
If you really want to know your way around LibGDX, you have to take baby steps, at least for the next two-weeks.

Here's something you can start with. I've tried to comment as much as I could.
B4X:
'==================================================================================================
    #Region  Project Attributes
        #ApplicationLabel: LibGDX Test
        #VersionCode: 1
        #VersionName: 1
        'SupportedOrientations possible values: unspecified, landscape or portrait.
        #SupportedOrientations: Landscape
        #CanInstallToExternalStorage: True
    #End Region

    #Region  Activity Attributes
        #FullScreen: True
        #IncludeTitle: False
    #End Region
'==================================================================================================

'==================================================================================================
    Sub Process_Globals
        Type Sprite( _
            Texture As lgTexture, _
            TextureRegion As lgTextureRegion, _
            ActiveFrame As Int, _
            ActiveFrameX As Int, _
            ActiveFrameY As Int, _
            FramesPerRow As Int, _
            FrameSizeX As Int, _
            FrameSizeY As Int, _
            FPS As Int, _
            TimeStamp As Long _
        )
    End Sub
'==================================================================================================

'==================================================================================================
    Sub Globals
        'Required LibGDX stuff
        Dim GLView          As View
        Dim lGdx            As LibGDX
        Dim Gl              As lgGL
        Dim Camera          As lgOrthographicCamera
        Dim Batch           As lgSpriteBatch

        'Our custom sprite object
        Dim Ryu             As Sprite
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
        'Initialize the LibGDX layer
            GLView = lGdx.InitializeView("LG")
            Activity.AddView(GLView, 0%x, 0%y, 100%x, 100%y)
    End Sub

    Sub Activity_Resume
        If lGdx.IsInitialized Then lGdx.Resume
    End Sub

    Sub Activity_Pause(UserClosed As Boolean)
        If lGdx.IsInitialized Then lGdx.Pause
    End Sub
'==================================================================================================

'==================================================================================================
Sub LG_Create
        Batch.Initialize
        Dim Texture As lgTexture 'Initializes the texture object, meaning our source bitmap (PNG)
        Dim TextureRegion As lgTextureRegion 'Initializes what will be our animated sprite

        Texture.Initialize("ryu.png") 'ryu.png is located in the files folder
        TextureRegion.InitializeWithTexture(Texture) 'The texture "Texture" we just initialized is assigned to our animated sprite "TextureRegion"

        'If you look above, we've started by creating a custom type named "Sprite".
        'LibGDX has its own Sprite object, by you can also create something similar, as seen in this example.
        'Since Java passes objects by reference (and B4A is Java), "Ryu.Texture" is nothing but a pointer (like a shortcut)
        'to the original texture object "Texture" the same goes for "Ryu.TextureRegion".
        Ryu.Texture       = Texture
        Ryu.TextureRegion = TextureRegion

        'The animation will run at 24 frames per second, independent from the engine (LG_Render)
        'which should ALWAYS, I repeat, ALWAYS run non-less than 60 frames per second.
        Ryu.FPS = 24
        Ryu.FramesPerRow = 8
        Ryu.ActiveFrame = -1 'Why -1 and not 0? Explained in the Sub Animation
        Ryu.FrameSizeX = 178
        Ryu.FrameSizeY = 178
End Sub

Sub LG_Resize(Width As Int, Height As Int)
    'Sets the camera viewport
        Camera.Initialize

        'The reason I'm using SetToOrtho2(True) is because I want my x.y origin
        'to be located at the upper-left corner of the screen.
        Camera.SetToOrtho2(True, lGdx.Graphics.Width, lGdx.Graphics.Height)
End Sub

Sub LG_Render
    'Clears the screen
        Gl.glClear(Gl.GL10_COLOR_BUFFER_BIT)

    'Updates the matrices of the camera
        Camera.Update

    'Uses the coordinate system specified by the camera
        Batch.ProjectionMatrix = Camera.Combined

    'Sprite Animator
        Animation

    'Renderer
        Batch.Begin
            'Ryu's Texture Region is drawn here, sized 300x300 pixels on-screen.
            'Remember, this size is independent of it's original frame size (178x178).
            Batch.DrawRegion2(Ryu.TextureRegion, 0, 0, 300, 300)
        Batch.End
End Sub

'The Dispose event is EXTREMELY IMPORTANT, if neglected you'll have memory leaks
'You don't have to dispose TextureRegions, only Textures. <-- FOR OUR SPECIFIC CASE
Sub LG_Dispose
    Batch.dispose
    Ryu.Texture.dispose
End Sub

Sub LG_Pause
    LG_Resume
End Sub

Sub LG_Resume
End Sub
'==================================================================================================

'==================================================================================================
'This is my custom-made sprite animator. Like I said, you may use LibGDX own Sprite object for this purpose,
'but I think this is a good opportunity to understand the basis of sprite animation.
Sub Animation
    'Every 1/24 of a second, a new frame will be displayed.
    If DateTime.Now - Ryu.TimeStamp > (1 / Ryu.FPS * 1000) Then
        'Advances ONE frame. Since Ryu.ActiveFrame was initialized to -1, the first frame to be displayed will be FRAME 0.
        Ryu.ActiveFrame = Ryu.ActiveFrame + 1
        If Ryu.ActiveFrame > 9 Then Ryu.ActiveFrame = 0

        'Timestamps the new frame
        Ryu.TimeStamp = DateTime.Now

        'This formula gets the X, Y texture coordinates based on the ActiveFrame index.
        Ryu.ActiveFrameX = Ryu.ActiveFrame Mod Ryu.FramesPerRow
        Ryu.ActiveFrameY = Floor(Ryu.ActiveFrame / Ryu.FramesPerRow)

        'This is where the magic happens.
        'Ryu's sprite (Texture Region) will be section of it's own texture (Ryu.Texture) sized 178x178 pixels.
        Ryu.TextureRegion.SetRegion(Ryu.ActiveFrameX * Ryu.FrameSizeX, _
                                    Ryu.ActiveFrameY * Ryu.FrameSizeY, _
                                    Ryu.FrameSizeX, Ryu.FrameSizeY)
        'OPTIONAL
        'Because I like to have the x,y origin (0,0) at the upper-left corner, I have to flip the texture region.
        Ryu.TextureRegion.Flip(False, True)

        '################################################################
        'The Texture Region is now ready to be displayed in a Batch.Draw!
        '################################################################

    End If
End Sub
'==================================================================================================

If you're interested in a more advanced sprite animation, click below.
This small project will display Ryu's "idle" animation, which is comprised of the first 10 frames (left-to-right, to the bottom) of the texture file.
Notice this line of code in the Animation sub:
B4X:
If Ryu.ActiveFrame > 9 Then Ryu.ActiveFrame = 0

If you wanted to display a punch, you only need to remember that the corresponding frames are [10 to 13]. You could create an array to store the animation size of each character move. For example:
B4X:
Type Sprite(..., ..., ..., Moves(,) As Int, ActiveMove As Int)

...

'Constants
'------------------------------------------------------
Dim numberOfMoves = 2 As Int
Dim numberOfColumns = 2 As Int
Dim firstFrameColumn = 0 As Int
Dim animationSizeColumn = 1 As Int
'------------------------------------------------------

Dim Moves(numberOfMoves, numberOfColumns) As Int

'Suggestion: Read the following from a text file (or SQLite database)
'------------------------------------------------------
Dim IdleIndex = 0 As Int
Dim PunchIndex = 1 As Int

Dim IdleFirstFrame = 0 As Int
Dim IdleSize = 10 As Int

Dim PunchFirstFrame = 10 As Int
Dim PunchSize = 4 As Int
'------------------------------------------------------

Moves(IdleIndex, firstFrameColumn) = IdleFirstFrame
Moves(IdleIndex, animationSizeColumn) = IdleFirstFrame

Moves(PunchIndex, firstFrameColumn) = PunchFirstFrame
Moves(PunchIndex, animationSizeColumn) = PunchFirstFrame

Ryu.Moves = Moves

Now we could replace:
B4X:
If Ryu.ActiveFrame > 9 Then Ryu.ActiveFrame = 0
With:
B4X:
Sub MainGameCycle
    ...
    ...
    'punch = punchIndex = 1 (for example)
    ...
    If playerAction.PunchBtn Then
        SetMove_Ryu(punch)
    End If
    Animate_Ryu(Ryu.ActiveMove)
End Sub

Sub SetMove_Ryu(moveIndex As Int)
    Ryu.ActiveMove = moveIndex
    Ryu.ActiveFrame = Ryu.Moves(Ryu.ActiveMove, firstFrameColumn)
End Sub

Sub Animate_Ryu(moveIndex As Int)
    Ryu.ActiveMove = moveIndex
    Dim lastFrame = _
        Ryu.Moves(Ryu.ActiveMove, firstFrameColumn) + _
        (Ryu.Moves(Ryu.ActiveMove, animationSizeColumn) - 1) _
    As Int

    If Ryu.ActiveFrame > Ryu.Moves(Ryu.ActiveMove, lastFrame) Then
        Ryu.ActiveFrame = Ryu.Moves(Ryu.ActiveMove, firstFrameColumn)
    End If
    ...
    ...
    ...
End Sub
 

Attachments

  • ryu.png
    141 KB · Views: 620
Last edited:

melonZgz

Active Member
Licensed User
Longtime User
I was in your situation a few months ago, so I understand you perfectly.
In short: Go for LibGDX. Even if your game is simple, the performance will be better.
Some months ago I made a big mistake, I started to write my first game (very simple game, a flappy clone with cute graphics, a shop, multiple modes...), and as it was rather simple I started using gameSpriteView library. It was OK in my phone (a MotoG), but when it was almost finished, I realized that the performance was very different depending on which device I was testing it, and stuttering a lot in some devices. So I had to start again, and start learning GDX.
What I did was studying the examples provided. First just learn how to draw an image in the screen. then you can try to animate it (example animation). Also the flappy game example was so usefull for me.
Once you understand some concepts like textures, regions, sprites, spritebatch, camera, you can work very fast.
And you can try box2d, it's great! It opens you a new world of games, where you can let the physics engine do the work. You'll "only" have to check collisions and sensors to see what happens in your world. My first game is going to be a libGDX+Box2D game.
About the math background, for a 2D game you don't have to be an engineer, but you need to have some knowledge about vectors. The more the better.

Another piece of advice:
- Don't be tempted to use Lists, Maps or any other fancy objects. They will slow your game down.
- Use Arrays.
Is this true?? is really noticeable? Because in my game is based on lists, sometimes with more than 50 elements.
What I do in each step is something like


B4X:
For Each knight As cKnight In lstKnights
    knight.draw(DeltaTime)
Next
Which I read somewhere it was the fastest way to get the elements from a list. If using arrays is faster I think I'll get better performance for my game.

PS: First post in these forums after years just watching. I'll be more active since now.
PS2: Sorry for my english!
 

wonder

Expert
Licensed User
Longtime User
is really noticeable?
Well, depends. On a fighting game (two-characters + background), I would probably be fine, but on a RTS game, where you can have hundreds of characters on screen and/or the same amount of A.I. agents, favoring arrays is a must. The performance gap between the two will be noticeable. (@Informatix, correct me if I'm wrong).

Of course, you can use lists/maps/databases to organize and load your assets (textures, sound, music, maps), though. Just not in-game.
 

Informatix

Expert
Licensed User
Longtime User
Is this true?? is really noticeable? Because in my game is based on lists, sometimes with more than 50 elements.
The operations that you perform on a collection can be independent from the number of elements in the collection or very dependent according to the type of collection, and some collections have known limitations due to the way they are implemented or the lack of some functions: extending or shrinking an array is very expensive (arrays are usually of fixed size; they are not supposed to have a dynamic size), sorting a map or an array is a bit complicated in B4A... That's why there's no generic answer. Depending on the operations to perform and on their frequency, you will choose a collection or another. If performance is not at stake, you will choose the most convenient collection.
That being said, the fact is that many collections are based on an array (List, for example, is in Java an ArrayList). So, all the overhead can be removed by using directly arrays. To remove its main limitation, an array can be sized big enough to hold all possible elements created by your game, and a simple index variable will keep track of the last cell filled. When you add an element, you increment the index and fill the available cell. There's still a problem with the sorts and removals but there are solutions for these cases too. The question is: do you really need that? If a List does the job, use a List.
 
Last edited:

wonder

Expert
Licensed User
Longtime User
How about creating a large array with a fixed MAX_VALUE?
B4X:
'=== main cycle ===
Dim MAX_ENEMIES_ONSCREEN = 256 As Int
Dim Enemy(MAX_ENEMIES_ONSCREEN) as Whatever

If Enemy(i).Active = TRUE Then
    ...
    ...
End If
'=== main cycle ===
Is it a bad practice?
 
Last edited:

StefanoAccorsi

Member
Licensed User
Longtime User

This will be very very useful! Thank you @wonder I'll let you know.
 

StefanoAccorsi

Member
Licensed User
Longtime User
Ok, big steps ahead from the last post, thank to your hints.

But still I have a big problem: debugging. When I started to work with libGDX I understood that I have to compile & run in "release" mode, since libGDX works in a different thread and that, as written in the great @Informatix tutorial, "You have to use the Log() function to debug your game."

But does Log() work in release run? Since I can't see any of my logs in the right window, as I see in not-libGDX programming.

And if I try to run the program in debug mode, it crashes as soon as it starts, while in release it doesn't: it can't find resources files ...

As usual thank you.
 
Last edited:

ilan

Expert
Licensed User
Longtime User
hi

i am not sure if i post this question in the right thread but since it is about box2d i am asking it here.

i am working now on a libgdx - box2d game and i have created a world with some physic bodies and a car (that is connected with prismatic joints + revolute joints, bla bla bla.)

i set 0 to the wheels friction. the value should be between 0 - 1. according to box2d manuals (Chapter 7.2 http://box2d.org/manual.pdf)

friction 0 means NO FRICTION, friction 1 means a very high friction but what i get is a opposite behavior (by a circle body!)


is it a bug or am i doing something wrong ?

EDIT: the same for lgBox2DEdgeShape and lgBox2DPolygonShape
 
Last edited:

Informatix

Expert
Licensed User
Longtime User
You should post in the libGDX thread instead.
Did you try the friction demo? Do you have strange results with it?
 

ilan

Expert
Licensed User
Longtime User
You should post in the libGDX thread instead.

sorry

Did you try the friction demo? Do you have strange results with it?

YES! the same behavior.
i just tried your example "Varing Friction"
and changed this line:

B4X:
Dim friction(5) As Float = Array As Float (0.75, 0.5, 0.35, 0.1, 0)

to

B4X:
Dim friction(5) As Float = Array As Float (0, 0, 0, 0, 0)

and all box are sliding but they shouldnot slide because friction is 0
when i set to 1 all stay at place
 

Informatix

Expert
Licensed User
Longtime User
That seems normal. If there's no friction (=0), objects should slide at full speed. And it's exactly what the manual says.
 

ilan

Expert
Licensed User
Longtime User
That seems normal. If there's no friction (=0), objects should slide at full speed. And it's exactly what the manual says.

you are right, sorry.
i misunderstood the manual. friction strong means NO sliding, i tought strong friction means a very strong sliding.
(result of my weak english)
 

Hilen

New Member
Licensed User
I have been playing are writing games since Pong. Very good points to consider here. As you mention, there is much more to making a great game than just coding. Games take a ton of thought and planning and as a wise man once said...

..."Imagination is more important than knowledge." - A. E.

One small thing to add...Things like Play-ability and Shelf-life must always trump fancy graphics.
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…