Android Tutorial How to make games

How to make games

A great idea, but a disappointing result

You woke up one morning with a great idea for a game. You rushed to your phone to convince your best friend to do the artwork, your uncle to create sounds and music, and your sister to build a web site to promote your future success. Unfortunately, three weeks later, and after a few sleepless nights, you have to face reality: your game is crap. It has a nice concept, it is pretty, it has cool music and the screenshots are very engaging on the web site, BUT it is slow, it frequently has memory problems, it does not adapt well to different screen resolutions, the animations are choppy, the gameplay is poor, the special effects have been reduced to... none, the AI is dumb as a bag of hammers, the collision detection system is far from perfect (and maybe you do not even know what a collision detection system is), the sounds do not mix with the music and it is necessary to know a whole bunch of rules before playing. In short, it is probably time for you to read this tutorial.

A few words about me

I’m a professional developer and I made a few games in the 80’s, but I never worked in the game industry and my experience in creating games for Android is rather limited, so I don’t ask you to blindly trust my words in what follows. But I am passionate since long by games, how they are designed, the algorithms they use, how they solicit your imagination, what skills and tools they require, so I’m not without some knowledge in that domain. And my goal is less to explain you how to make a hit game (that I’ve never created myself) than to help you avoid the most common pitfalls and to give you some directions.

What’s a game?

From Wikipedia:
“A game is structured playing, usually undertaken for enjoyment and sometimes used as an educational tool. Games are distinct from work, which is usually carried out for remuneration, and from art, which is more often an expression of aesthetic or ideological elements.
[…]
Key components of games are goals, rules, challenge, and interaction. Games generally involve mental or physical stimulation, and often both.”

As said above, your game must have goals and rules, and your player needs to know them when he/she’s playing. The goals have to be obvious or clearly explained at the beginning of the game: collect all gems, drive fast to be first, eat all food dots, kill all monsters, survive until dawn, etc. The rules can be explained along the way, with tutorials, panels between levels or help balloons, but they have to be explained and easy to remind. If your game has a steep learning curve or too many rules, it has a great chance to end in the depths of the Google Play Store. Having to read a book for playing a game is something to avoid in the Android market.

Your game must propose progressive challenges, and that’s probably one of the most difficult tasks when you create a game. The game should be easy at the beginning to allow the player to become familiar with the controls, to fully understand the basic rules, to be in the mood... and the difficulty should increase regularly. Make it too difficult at start and you will discourage casual players. Make it too easy and it will look more like a demo than a game. Nowadays, this task is devoted to a specialist (the game designer, or level designer) in gaming companies and is considered as one of the keys to success, so don’t overlook it. Put your game in many different hands and observe how people play it. Make changes and test again. Take note of what people say. Don’t think you know better than everyone what is fun or cool in your game, and what’s challenging or not.

Your game must be playable: the controls have to be easy to use, the controlled object has to react precisely and without delay, the secondary screens (e.g. the inventory or map screen) have to be accessed quickly, the menus have to be clear... It’s very frustrating when you lose because you were unable to move precisely your character or because you didn’t open the right screen on time to select a spell or a weapon. Any problem with the controls will increase the difficulty of your game. And keep in mind that your players are not as skilled as you are. You played many times to your game, they did not. So don’t expect they will master the controls very quickly, especially in a driving game where a small change of direction can make all the difference between success and failure.

A game is a complex combination of goals, rules, challenges, graphics, audio, special effects, gameplay, controls, atmosphere, etc. and mixing all this to create something great is very difficult. Whatever your ambition is, you will see that creating a game is not the easiest work and takes a lot of time. You will face many technical and artistic problems, and maybe you’ll abandon more than one project before reaching your objective. So I hope that the following advices will speed up your development and prevent any bad choices.

Prepare your work

Coding a game is not really different from coding another type of application. You have to know what’s the result to obtain, what are the tools you need and how you are going to use them. So no surprise here:
  • Limit your dreams to the reality of your skills. Don’t imagine that your first game will compete with Riptide GP, Angry Birds or Ingress. It’s impossible. Start by a simple game, with simple rules, and if you’re successful, you will add complexity, special effects, new levels, etc.
  • Write the rules and the logic of your game, then translate them into pseudocode, and finally use this pseudocode to comment your classes and functions. That will make things clear and ease any future modification. Note that it’s mandatory if you want to work with a teammate.
  • Draw your game screens on paper. Things are usually very different in your mind and on the paper, with the right size. You will realize, for example, that a touchpad takes a lot of place or that it’s not a good idea to put the action button at the top because it is too far to be used quickly.
  • Collect tools, libraries, snippets of code and tutorials. If you don’t know how to do some parts of your game, learn by reading tutorials and books. If you don’t have the right tools, search them or write them. Become familiar with the numerous libraries of Basic4Android. It’s too bad when, in the middle of a development, you realize that you need a library which does not exist yet.

Tools and libraries

You could use only the standard libraries of Basic4Android to make a game but this game would be very limited. It is a lot easier and faster to create a game with the right tools. Here’s a selection of libraries at your disposal in February 2014:
  • Game engines: LibGDX, RSAndEngine.
  • Rendering: OpenGL, OpenGL2, jPCT-AE, GameView, Accelerated Surface, Game Sprite.
  • Animation: Animation, AnimationPlus, NineOldAndroids, TweenEngine.
  • Audio: MediaPlayer, SoundPool, AudioTrack, OpenSL.
  • Input: Gesture Detector, PhoneAccelerometer.
  • Artificial intelligence: SteeringBehaviors.
  • Physics: JBox2D, ABPhysics.
  • Files/data: JSON, SQL, XML, RandomAccessFile.
  • Networking/multiplayer: Network, HTTP, GamePlayServices.

The libraries of the “game engine” category provide a framework to create various kinds of games. They include a rendering engine for 2D, a physics engine (Box2D), an audio engine, a tiled map renderer, a scene graph and a lot of helper classes to ease your burden. They should be your first choice.
I’d recommend LibGDX because it has plenty of features and a very fast rendering engine, but it is a big fat baby (about 2.8 MB for the full version and 1.7 MB for the lite version), so you could prefer a combination of Accelerated Surface, Game Sprite or OpenGL with MediaPlayer, SoundPool and ABPhysics for a lightweight application.

For 3D games, I’d recommend a combination of jPCT-AE + MediaPlayer + SoundPool.

The LibGDX, RSAndEngine and jPCT-AE libraries belong to the OpenGL ES family. Their rendering engine makes an optimized use of the OpenGL ES library and fully benefits from the hardware acceleration.
The GameView and Accelerated Surface libraries belong to the accelerated Canvas family. They call also the OpenGL ES methods, but without any optimization. They cannot be as fast as the libraries of the OpenGL ES family, and it’s worse with the Android versions prior to Honeycomb because they cannot benefit from the hardware acceleration.
The Canvas class of Basic4Android belongs to the Skia Canvas family, which has many drawbacks and should not be used in a game.

For a 2D game with two dozens of graphic objects on screen, it doesn’t matter if you choose a library of the OpenGL ES family or a library of the accelerated Canvas family. A few games have been created with the Accelerated Surface library and they didn’t exhibit a limited performance on most devices. But for games more demanding, for 3D or just for peace of mind, you should prefer a library of the OpenGL ES family.

Beside the above libraries, you may find useful PreferenceActivity or AHPreferenceActivity to save the game options, ABExtDrawing to create or transform your bitmap images, AHLocale to translate your application to different languages, Threading to run subs on separate threads, and Reflection of course which gives a full access to the Android API.

You will need also tools to create your images, your sounds, your animations, your 3D models... You have probably your preferences in each category. For Box2D, it exists two scene editors: the C2D scene editor, which is free, and R.U.B.E, which is well worth its price. If you have no artistic skill and no artist in your team, you may find graphic resources on deviantart.org or opengameart.org, and use Bfxr to generate sounds. For music, alas, you have to buy royalty-free songs or take music lessons.

OpenGL ES

As I explained, OpenGL ES (Open Graphics Library for Embedded Systems) is at the core of the best rendering engines so I’d like to give you a short introduction to this library.

This library has been wrapped for Basic4Android and is named OpenGL for the version 1 and OpenGL2 for the version 2. The version 2 eliminates most of the fixed-function rendering pipeline in favor of a programmable one. Almost all rendering features of the transform and lighting stage, such as the specification of materials and light parameters formerly specified by the fixed-function API, are replaced by shaders written in GLSL, the shading language. As a result, OpenGL ES 2.0 is not backward compatible with OpenGL ES 1.1.

Nowadays, almost all Android devices support OpenGL ES 1.1 and OpenGL ES 2.0, but the version 2 is more complex to learn than the version 1.x and doesn’t offer a significant increase in performance, so if you’re new to OpenGL, you should start with the version 1.1.

Jelly Bean 4.3 introduced support for OpenGL ES 3 but this version is not yet available to Basic4Android users and needs devices with appropriate drivers.

If you intend to use directly OpenGL ES, and not a library with higher level functions, be prepared for a serious headache because it’s a somewhat complex library. If you’re scared by geometry or by words like “frustum”, then OpenGL is maybe not for you. ;)

There are a lot of tutorials on Internet devoted to OpenGL, so I won’t add one. Here’s just a list of the main features and things to know:
  • OpenGL is basically a triangle renderer. Thus, a rectangle drawn by OpenGL is made of two triangles. Each triangle is made of three points called vertices, which have a position in space: x, y, z.
  • Each rendered object has a geometry (a shape made of triangles), a set of colors, a texture (an image applied to its surface) and a material defining how this object interacts with light.
  • Objects are seen by a camera. The camera can move, rotate, and zoom in or out.
  • OpenGL constructs a 2D view of a 3D scene from the camera position. It uses one of the two available projections: parallel (the objects size is always the same regardless of the distance of objects from the camera) or perspective (the objects are smaller when they are far).
  • The size and aspect ratio of the 2D view on screen are defined by the viewport.
  • The Y-axis is pointing upwards.
  • Color values range from 0 to 1.
  • OpenGL stores its data in native heap memory, not in the Java heap memory of your application, and thus is not limited by the VM heap size and is not affected by garbage collection. It’s a big advantage over the Canvas-based solutions.

Your first steps with OpenGL will probably be disappointing because it needs a lot of code to do simple things, and the result is often not faster than an accelerated Canvas library. In fact, you have to use a batching technique and advanced features such as the Vertex Buffer Objects to make the most of OpenGL. So, is it worth to spend time learning OpenGL since the API provided by LibGDX and jPCT-AE are already optimized and a lot easier to use? IMHO no, except for very particular needs, e.g. if you intend to add a realistic water ripple or wave effect to your game and you didn’t find the appropriate code on Internet.

Now, you are able to make reasoned choices and select the right tools. It’s time to write your code, but what to do first? And what to do next?

From the core to the shell

A game is usually written from the core (the functions that draw, compute or move your objects) to the shell (the artwork, the user interface, the music, the bells & whistles, etc.). In a gaming company, it’s a bit different because people work in parallel, but when you’re alone or a very small team, you should follow this order because:
1) You will be able to try out the core of the game in the smallest amount of time. You will see quickly what’s really lacking, what does not work, what is technically too difficult, etc.
2) It is less discouraging to abandon a project at an early stage for a very technical reason, than to abandon it near the end for the same reason.

So your first task is to produce a playable prototype with the core mechanics of the game. When this prototype will be fully satisfying, and it might not be before long, then it will be time to render your characters with their final texture, add sounds and music, save the game state on disk, make nice menus, etc.

Use your imagination

Even experienced game makers face difficulties because each game is unique and challenge your skills. Sometimes there’s no easy solution and internet and books are of no help. You have to invent a new way of doing things or mix existing approaches in an unusual manner. It’s not uncommon with A.I. or special effects. Example: a laser FX. That’s why I’m used to say that your imagination will be as much requested as your skills.

The main functions of your game

To build your prototype, you have to create a set of specialized routines. They depend on the type of your game, but usually you have:
  • a loader: it loads the resources and initializes data
  • a screen manager: it selects the appropriate screen (menu, map, options, etc.) according to the game state and player actions;
  • an input handler: it processes the keyboard and touch events
  • a “brain”: it selects the actions of enemies
  • a position calculator: it computes all moves and calls the collision detector
  • a collision detector: it detects collisions between objects
  • an updater: it defines the new state of objects (wounded, dead, paralyzed, hasted, etc.) and computes the score and lives
  • a renderer: it draws the objects on screen
  • a resetter: it resets all data for a new game

For the clarity of your code and to make changes easier, create a class for each object type (a class for the hero, a class for his horse, a class for his enemies, a class for the map, a class for the furnitures, a class for the weapons, etc.). Then, create a specialized routine (loader, updater, renderer, etc.) in each class. You can choose another model, where the routines are in their own code module. In this case, each class makes a call to the common routine with its custom parameters.

In the main class, keep track of the game state (“loading”, “ready”, “running”, “paused”, “game over”, etc.).

If you don’t use a game engine, add the classes that will handle graphics, sounds, animation, files, input, physics, threading and networking at a lower level. These classes will be separated from the logic of the game and can be reused in other games.

Adapt your game to the screen

The first stage of your game is the loading of assets, and quickly a problem will arise: your background image has a size of 800x600 which does not fit the current screen resolution in landscape mode (854x480). What can you do?
  • Adjust the image size, but keep the same aspect ratio. Reduce the image dimension which is larger than the screen dimension and compute accordingly the other dimension. In my example, the image height is superior to the screen height so the image height is set to 480. The width becomes 480 * 800 / 600 = 640. The aspect ratio remains the same: 640/480 = 800/600 = 1.3333. By doing this, I get black stripes on the sides, but the image is entirely on screen whatever the resolution may be.
  • Stretch the image. The width and height are set to the screen size. I recommend using a nine-patch (a drawable with stretchable areas) in this case or your image will look distorted.
  • Draw your image as is. The width and height are not changed (or they are just scaled to the device density so that your image gets the same physical size on all devices). It’s too bad for the guys with small screens!
The same reasoning can be applied to the game area, of course.

This problem with resolutions brings a new question: what is the ideal size for my images? The answer is simple: there’s none. Create three versions of the same image with different resolutions and use the one that needs the smallest scaling. If you don’t want to bother with that, create large images. The scaling down of a large image will produce a better result than a small image scaled up.

In one of my applications, I decided to set all background images to 1040x640. The image is large enough to scale up nicely on large screens and small enough for small screens. If I lose a bit of details, it’s not important because it’s just a background. This size is exactly in the middle of 800x480 (WVGA) and 1280x800 (WXGA). For the other graphic objects, I chose to size them properly for a 1280x800 screen. They don’t suffer too much from the scaling down.

To test different resolutions or densities, you can use the emulator.

Keep an eye on memory

Don’t forget that an image takes up space in memory and that some devices allocate a very limited amount of memory to your application. So, if you want to load a bitmap, use the LoadScaledBitmap function of the Accelerated Surface library to resample and resize the image to the right dimensions.
This problem will be less annoying with libGDX because this library transfers the loaded textures in native heap memory.

In all cases, Out of Memory is an error to avoid at all costs. This error crashes the game, and even when you trap it, it’s not easy to recover from it. Note that LoadBitmapSample tries to sample down your images when this error occurs, but I cannot recommend relying upon this feature. First because that means that you don’t manage well your resources, and second because nobody likes to play a game with ugly images.

To track the memory usage of your application, you can use the Monitor tool provided with the Android SDK and/or log the FreeMemory property of the StrictMode library.

To reduce the memory usage, there’s not a lot of solutions: try to use smaller images, change their color format to RGB565 if you don’t need transparency (see the ReduceColors function of the Accelerated Surface library), set to Null the bitmaps or canvas instances that you no longer use, and/or store your images in native heap memory with either a library of the OpenGL ES family or the Native DirectBuffer library (reserved to experts).

All that you may read about recycling bitmaps is mostly useless for the new versions of Android. This was only useful in some cases with Gingerbread and older versions. It is now deprecated.

If you still have problems with memory, you can add this line in the manifest to get more memory with Android versions >= 3:
B4X:
SetApplicationAttribute(android:largeHeap, "true")
This line is of no use for the libraries of the OpenGL ES family except, of course, if you store in the Java heap memory a huge volume of data (e.g. an array with millions of float values).

From the world to the screen

Using the screen coordinates to position your graphic objects is sometimes a bad idea. Think to a chess board where the pawns can only move from a tile to another. It’s more convenient to position them by indicating a tile than computing their coordinates in pixels. Think also to a big world that cannot fit entirely on your screen. It’s more convenient to position your characters with world coordinates than with the limited screen coordinates. And sometimes you don’t have the choice. The physics engine Box2D, for example, doesn’t use pixels, only meters.

When you use a library based on OpenGL, you can define with the viewport a different unit scale to position and size your graphic objects. With the other libraries, you have to create functions that make the conversion. Examples:
B4X:
Public Sub FromTileXToPixelX(TileX As Int) As Int
Return TileX * TileSize
End Sub

Public Sub FromWorldXToScreenX(WorldX As Int) As Int
If WorldX < ScreenLeft Or WorldX > ScreenRight Then Return –1
Return WorldX – ScreenLeft
End Sub
As you can see, these are very simple math, and very useful. In the second example, the boundaries of the screen in world coordinates are ScreenLeft and ScreenRight. These two X-coordinates limit the current area of the world which is drawn. If the given parameter is outside the boundaries, then –1 is returned; the object is not on screen and shouldn’t be drawn.

Draw only what’s needed

Assets are loaded, data are initialized, and all actors of the battle are ready to fight. It’s time to draw the battlefield and the sprites of the warriors at their initial position. Once rendered, the first computations will take place to know who strikes who, who is wounded, who is dead, who moves and where, etc. And the renderer will be called again to show the new situation. How to sequence these different phases properly?

In libGDX, for example, the Render event is called continuously. You can put all your game logic in this event and sequence the phases as you wish (input handling, computation, rendering, then input handling, computation, rendering, and so on). In the Accelerated Surface library, a Timer raises regularly the Update event, then the Draw event, if you enabled that sequence with StartRegularUpdateAndDraw. It’s advised to put only the rendering functions in Draw, and everything else in Update. If the processing of one of the events takes more time than the Timer interval, the Timer waits before firing the next event so you cannot be in a situation where you start to draw with an incomplete calculation. In the GameView library, you have to set a Timer and use its Tick event. It’s like the Render event of libGDX; you can put everything here and order your phases as you wish.

Regardless of the number of things to do between two renderings of a scene, everything has to be done in less than 16ms, rendering included. You could set this Timer interval to a longer value with some libraries but I advise against it. A span of 16 ms will display about 60 frames per second, which is an ideal rate for your game. First because the brain won’t have to create intermediate images to give you the feeling of a smooth and continuous motion, and second because your hardware runs at its best with this rate. Some devices are capped to 40fps, but it is still excellent.
If one of the phases takes too long, but only from time to time, it will introduce an irregularity in the sequence and your animations will be choppy. If a phase takes too long, but always with the same duration, your game will be slowed. Usually the phase involved is the rendering phase. What can you do when that happens?

There are two main reasons for a slow rendering: your graphic objects are too numerous or too complex. The first thing to do is to avoid rendering objects that are not visible, either because they are hidden by something else or because they are off screen. The second thing to do is to limit the number of textures because OpenGL binds only one texture at a time and doesn’t switch quickly to another. Take the habit to use the texture regions of a texture atlas (see the documentation of your library). A third thing to do is to minimize the complexity of your rendering. Far objects do not need to be rendered with a detailed texture. Fast moving objects do not need to be anti-aliased. Composite backgrounds do not need to be recreated each frame (create a snapshot of the background and draw this snapshot). Disable blending for opaque images (if possible) and minimize the transparent areas. Allow your players to disable some special effects (e.g. fog, water reflection, shadows, etc.). There are other optimizations but, if you apply these first three, you should gain many fps.

I talked about the common case where the rendering has to be regular, but in a lot of games, like puzzle games, it’s not necessary and you should avoid soliciting constantly the CPU or the GPU for nothing. With libGDX, for example, you can stop the continuous rendering and raises the Render event only when needed. Your device battery will love it!

Mind the step

On a device, your application is not alone. There are services running, e.g. to check your mailbox regularly or to scan programs for viruses, and they can alter the flow of your game during short periods of time. You cannot do anything to prevent this, but you can adapt your game to these sudden changes by altering the time step. What’s this?

We saw in the previous chapter that you have only 16ms to do all your computations and render a scene. This span is not the time step. It’s just a timer interval and it will be impacted by a slowdown of your device. The time step is in fact a float value that defines the speed of your game. An example will be better than a long explanation:
Each time that you move an object in your game world, you increase or decrease its coordinates. If you do X = X + 2, two units are added whatever the elapsed time between two frames. If you introduce a time step, the formula becomes: X = X + (2 * TimeStep). With this time step, you can accelerate or decelerate your game at will, just by changing this value. Set it to the delta of time between two frames and your objects will move faster when the device is slowed. The player will see a constant move.
A real example:
B4X:
Actor.X = Actor.X + Speed * lGdx.Graphics.DeltaTime
Speed is the speed property of the object to move and DeltaTime the time step. It is expressed in seconds between two frames. If everything goes well, its value should be close to 16/1000.

Sometimes the interval between two frames is very long (it’s the case when the antivirus of my phone checks the launched application) and the time step causes an issue called the tunnel effect. The step is so great that the move is really big, and your object can cross walls (it is moved directly on the other side). To avoid this, you should limit the value of your time step. Example:
B4X:
DeltaTime = Min(lGdx.Graphics.DeltaTime, 0.05) 'max=50ms i.e. 20 fps

You cannot use a variable time step in all cases. Physics engines require a fixed time step. Box2D, for example, works very well with a value of 1/60. If it’s too slow for you, you can increase it up to 1/30, but don’t go over.

....
 
Last edited:

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

RSAndEngine is probably the right tool for me. It's compact but powerful enough, it has a good tutorial, so let's study it! Just a question: why does Informatrix not link it in his guide? Because it's a dead project. Right? Did I understand correcrtly?
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
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 ...
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
    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
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 PuchIndex = 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 Foo
    ...
    ...
    'punch = punchIndex = 1 (for example)
    Animate_Ryu(punch)
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

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!)

The friction parameter is usually set between 0 and 1, but can be any non-negative value. A friction value of 0 turns off friction and a value of 1 makes the friction strong. When the friction force is computed between two shapes, Box2D must combine the friction parameters of the two parent fixtures. This is done with the geometric mean:

is it a bug or am i doing something wrong :confused:?

EDIT: the same for lgBox2DEdgeShape and lgBox2DPolygonShape
 
Last edited:

Informatix

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 :confused:?

EDIT: the same for lgBox2DEdgeShape and lgBox2DPolygonShape
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
sorry



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
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. :confused:
(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.
 
Top