Sunday, March 29, 2020

Tutorial 1.3: Plowing through the code first time


Crap that did take a lot of cursing to add code snippets in Blogger. Anyway

Didn't hit the "any" coding key yet, just browsing through the project that LibGDX created, and now imported/opened by Android Studio. With my usual sceptism. I typically dislike these standard framework kinda things. And on top, I find Java messy by nature in terms of having 6-thousand different classes for even doing nothing (nothing = new Nothing() ), and having too many meaningless names. The Jelly core runs on Grapefruit 3 with Fat Bertha accelerated test-stubs, on top of Walrus balls. Any idea what I'm talking about? I don't.

The project folder looks like a small battlefield, having lots of directories and files that confuse me. But, where you should focus on for now, is the "core". That's your playground, all the other stuff is multi-platform mumbo jumbo, and of course the necessary LibGDX framework files itself. If you open core/.../.../ JunkThrower.java, you actually see a few lines that look like they may have something to do with your game.And you will quickly see the 3 stages as well here: "born", "live", "die". Or as the function names would say Create, Render, Dispose.

Got to admit... only 1 file and 3 functions to start with... And if you click "compile", it even works! Now that's why I call, a friendly introduction.

package com.mygdx.game;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class MyGdxGame extends ApplicationAdapter {
    SpriteBatch batch;
    Texture img;
    
    @Override
    public void create () {
        batch = new SpriteBatch();
        img = new Texture("badlogic.jpg");
    }

    @Override
    public void render () {
        Gdx.gl.glClearColor(1, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.begin();
        batch.draw(img, 0, 0);
        batch.end();
    }
    
    @Override
    public void dispose () {
        batch.dispose();
        img.dispose();
    }
}


Now assuming that you never really wrote a game before, lets quit a bit on the stupid jokes for a moment, and let's try to actually explain something about game mechanics. In a very global way, every game deals with the 3 stages above. When Creating, you typically load resources. Like images, 3D models, sound effects, level-data. Or, at least you load parts of them. Or “packages” that tell what is available, and what CAN be loaded.

When you start Doom, it doesn't load ALL levels (textures, music, props...) right away, because that would never ever fit on your poor RAM or GPU. Big games will load whatever is needed in a level, or streams dynamically on demand when approaching new areas. The latter is usually the case in larger open-world games that don't have a level-by-level design. For this tiny phone game though, it's probably perfectly fine to just load (almost) everything at one. Except the levels structure itself.



And all that shall be created, shall be destroyed as well. Ashes to ashes, bytes to bytes. The Dispose function will be called when shutting down. You should clear resources, maybe save progress, kick him off the piano and stop the music. Now Java will do a lot of the "garbage collection" for you, but still there might be some doors you want to shut manually.




The real star of the show however, is the "render" function here. Though I find its name too specific. Rendering is about drawing the screen. Which happens every cycle indeed, many times per second (in order to get fluid animations, you really need 30 FPS at the very, very least). But there is more than just drawing things. Games have a lot going on in there "update" loop (which should have been a better name for this function, if you ask me):

·         Stream resources (if you have a big game that can’t load all at once)
·         Processing input (keyboard, mouse, touch)
·         Audio                    (stop, play, loop, adjust listener coordinates, modifiers, …)
·         Physics                 (simulate bodies flying, colliding, floating, responding)
·         A.I.                        (scanning, decision making, behaviour, path-finding)
·         And of course graphics
  



Anyway, you can still add all those parts. The important thing to realize is that this "render" function is being called lots of times per second, until you close the program. I believe LibGDX tries to reach 60 frames per second by default, but there is no guarantee you will actually make that. That shitty virus-scanner in the background may stall your performance, but you too have to be very careful with what you put in that “render” (or its sub-) functions. Lengthy routines like loading data or searching in gigantic arrays, is usually not a good idea.But hey, why not check out what the auto-generated code got for us?


    public void render () {
        Gdx.gl.glClearColor(1, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.begin();
        batch.draw(img, 0, 0);
        batch.end();
    }


Seems… it uses Embedded OpenGL for graphics. And it seems it first clears the background, then draws an sprite in the topleft corner (0,0)... Sprite? The drink? The mythical fairy? No idea why they ever called it that way, but yeah, sprites!  Think about PONG, a square flying over your TV screen. That's a sprite. Think about that purple glowing-thing that follows Link all the time in Zelda “Occarina of Time”. That’s a sprite. And even a fairy too!

Or instead of a simple sphere or square, you could put a picture on it, eventually a semi-transparent picture. For example, a plumber. And if you play multiple pictures in a row, you get an animation. Like Super Mario. These are sprites, and obviously your main ingredient for 2D games. Though 3D games still use sprites too, mainly for particles and small effects, like a flickering candle light.


Sprites are basically just rectangular areas on your display - or (partially) outside your view -, containing a (transparent) image. The size and position may change each cycle, and so may the content image. In addition, sprites my scale, shrink or rotate as well nowadays (in the Super Nintendo days, that was quite a hardware achievement). You could have 1 sprite, or dozens. Of course, more sprites means more drawing. Big numbers or very large sprites that overlap each other, may eventually slow things down. So typically you only want to render what is inside your view – which is fortunately fairly easy to do in 2D games.

So yeah, that's basically what we're gonna do. Load a bunch of images, make sprites, and move them around. Oh, and with a bit of sound, A.I., pathfinding, game-rules, touch-input and special effects of course.
 








Saturday, March 28, 2020

Tutorial 1.2: Game Concept + Planning

Yet another "how to waste your time on a game" tutorial, but what makes me think you should spend your precious time here? Well for one thing, probably because you have plenty of time now. But yeah you're right. It's about time we reveal our plans.

It would be a bit ironic if, 2 years later, somebody has become ridiculous rich with this "JunkThrower" game idea, while I'm still working as a bat-catcher on a Chinese wet market. But for the sake of humanity not getting deadly bored, let's risk it and reveal the ideas.


Did I just say "JunkThrower"? Making names has never been my best treat. My kids are named "boy" and "other kid". Guess how our next dog will be called? Stalin. I found that an appropriate dog-name. But yes, that's how the game is called officially / unofficially. Now guess that the game is about?

It's about throwing junk. Boulders. Crates. People. Especially the latter. As a bunch of people (or maybe monsters, mummies, panda bears, robots, whatever) are trying to reach your magic “Orb”. Don’t ask why, they just do. Like Bowser has kidnapped Peach for at least 450 times in the past few decades.

In a maze-like (top-view) map, foes will try to reach your Orb, making it grow. Like a balloon. If the orb gets stuck between the walls, it will explode, a black hole will appear, you get sucked into your phone, and game-over.

There isn’t much you can do about it, other than throwing those assholes away. Preferably against a wall, or against each other. Vice-versa, you may want to throw in health-crates and other good stuff back into your orb to…. Calm down a black hole? Whatever. You get the idea.

To make it more tactical, of course we can implement all kinds of traps. Acid pits, explosive barrels, building obstacles. That’s up to your creativity.

The game will be 2D, topdown, and as flat as Paper Mario. No complex story, photo-realistic graphics, or high-end 3D engines for a chance. For that, I can already torture myself with Tower22. Besides, I’m hoping a little bit that I can involve the kids at some point with drawing some sprites or recording sounds. But as you know, that only works if the graphics are simplistic and if concrete results can be shown within the next few minutes.

Tactics / Planning
Simplistic or not, you will learn, the hard way, that even seemingly simple games may still require a ton of work. And not just the programming work. Every stinky little effect has to come from somewhere. Drawings, sound effects, text-fonts, particle-effects, sprite images, music, level design, additional editors/tools to make those levels, and so on.

When starting from scratch, you will quickly ride your bike onto a steep slope. Which often is the point where quitters quit. Dreaming about games is fun, but actually making them requires discipline and iron will. I won't lie, it takes a lot of energy even to create stupid little things. Discouraging, really.

The trick is to satisfy yourself with small results. If you tell me now to lose 30 kg, I probably won't even start. If you reward me for every 1 kg I lose, I may give it a shot. Once the train is rolling, you will find it easier to keep on going, though at the same time it takes more and more progress to
satisfy. In any case, it is very helpful to make a solid plan. Then break down the plan into milestones, objectives, and small tasks. With "small tasks", preferably something that can be done in a day or two. So you can make a promise to yourself: try to finish at least 4 tasks every week. As long as you can put a fat "DONE!" mark on tasks, you'll be doing fine.

As for the steep incline in the early stage, make sure your first objectives aren't too far away. This may mean you first start with ugly dummy images, without sound, or just focus on rendering a nice background. As a visual oriented guy, I personally need to SEE things. So, with the game described above in mind, I'll first try to render some sprites. Just to see how that mechanic works in LibGDX. Keep in mind, as I'm writing this, my knowledge about LibGDX is as good as yours: pretty much none!

Next big thing will probably be rendering the level itself, which is basically just a large background image. Or, a lot of small tiled images placed in a cell-grid. There are multiple ways to go there. Well, as far as I can see now, this will be our planning. The chapters I'll write, shall follow this picture. Keep in mind I'm not a fortuneteller, so in reality we may go off-road or add things a little bit.

At the same time, I would advise not to dive too deep into a very specific aspect right away. Besides the LibGDX framework, you will also need your own mini "framework", "engine", or classes that properly describe your game in terms of levels, rules, players, enemies, objects, and so on. We won't be making a super versatile engine that can be used for the next Red Dead Redemption, but I will show you some ways to structure your game into logical parts, classes, ultimately reading to cleaner and better manageable code.