JGE++: A hardware accelerated 2D game engine for PSP/Windows

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

JGE++: A hardware accelerated 2D game engine for PSP/Windows

Post by dr_watson »

Introduction

JGE++ (Jas Game Engine++) is a hardware accelerated 2D game engine for PSP (using GU) and Windows. It's inspired by the popular game engine HGE on MS Windows. In fact the Windows' counterpart is basically a wrapper of HGE.

For more information about HGE, please visit its web site at:

http://hge.relishgames.com.

With JGE++, you can build a project as a Windows executable or a PSP EBOOT image with the same source code without any modification. This means the game development process, including coding, debugging and testing, can be done mainly in Windows. However, since JGE++ is still under development and not heavily tested, it is recommended that the PSP EBOOT image should be built and put onto a PSP for testing from time to time just to make sure everything is working properly.

Of course you may also put in platform specific codes with #if/#else/#endif.

SkyAnimator is introduced with JGE++ v0.2b. It is a visual tool written by
HuangYZ for creating sprite animations. HuangYZ has ported the runtime library to JGE++ and this gives JGE++ a very powerful animation system to play with.

Contents of the JGE++ package

- JGE++ v0.2b (source + lib)
- SkyAnimator lib
- JGE++ demo (source + assets)
- SkyAnimator demo (source + assets)
- StarBugz (source + assets)
- Mario Demo (source + assets)


Prerequisites

libpng
libz
mikmodlib


Directory Structure

Code: Select all

____JGE
|    |___HGE (Windows backend)
|    |___include (JGE++ header files)
|    |___lib
|    |    |___psp (lib files for PSP)
|    |    |    |
|    |    |    |___libjgesky.a (SkyAnimator lib)
|    |    |    |___libjge.a (JGE++ lib)
|    |    |
|    |    |___win (lib files for Windows)
|    |         |
|    |         |___JgeSky60.lib (SkyAnimator lib for VC6.0)
|    |         |___JgeSky71.lib (SkyAnimator lib for VC2003)
|    |         |___jge.lib (JGE++ lib Release version)
|    |         |___jge_debug.lib (JGE++ lib debug version)
|    |
|    |___src (JGE++ source files)
|
|___Demo
|    |___bin
|    |___Debug
|    |___JGEFramework
|    |___Release
|    |___src
|        |___GameApp.cpp
|        |___GameApp.h
|            
|___Mario (same structure as Demo)
|
|___SkyDemo (same structure as Demo)
|
|___StarBugz (same structure as Demo)


To build the JGE++ lib for Windows

Open "JGE.dsw" in JGE directory with Visual Studio 6.0. With the BATCH BUILD option, select "REBUILD ALL".


To build the JGE++ lib for PSP

Change to JGE directory, then

make clean
make install

or just run the batch file "mk.bat"


To build a project for Windows

Open "xxx.dsw" in the project directory with Visual Studio 6.0 and build for either "Release" or "Debug".


To build a project for PSP

Change to the project directory, then

make clean
make

or just run the batch file "mk.bat"


To run on Windows

You need DirectX 8.0+ installed.

Key mapping:

Code: Select all


PSP                     WINDOWS
------------------      -------------
UP/DOWN/LEFT/RIGHT      W/S/A/D
ANALOG CONTROL          UP/DOWN/LEFT/RIGHT
TRIANGLE                8 on NumPad (with NUMLOCK)
SQUARE                  4 on NumPad (with NUMLOCK)
CIRCLE                  6 on NumPad (with NUMLOCK)
CROSS                   2 on NumPad (with NUMLOCK)
SELECT                  CTRL
START                   ENTER
HOME                    F1
HOLD                    F2
NOTE                    F3
L                       Q
R                       E


To run on PSP

With firmware 1.50 PSP, use KXploit Tool to transfer the proper EBOOT.PBP onto your memory stick. Then you need to copy the entire "Res" folder in "bin" into the appropriate folder on your PSP too!


License

SkyAnimator(libjgesky/JgeSky60.lib/JgeSky71.lib) is free software. You can use it anyway you like at your own risk. Copyright (C) 2006 HuangYZ.

JGE++/JGE++ Demo/SkyAnimator Demo/StarBugz/Mario Demo are released under GPL and below is the license agreement:

"This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"


Special thanks to

- PSPSDK team
- devkitPSP team
- friends at pspchina.net
- Jasmine (James' lovely wife ^^)


Credits

JGE++:
Programmer - James Hui (a.k.a. Dr.Watson)

SkyAnimator and SkyAnimator Demo:
Programmer - HuangYZ

JGE++ Demo:
Programmer - James Hui
Artist - Zhen (TMD Games)

StarBugz:
Programmer - James Hui
Artist - Fung Lap Tong

Mario Demo:
Programmer - James Hui
Artist - Zhen (TMD Games)


Screenshots

SkyAnimator:
Image

SkyAnimator Demo:
Image

JGE++ Demo:
Image

StarBugz:
Image

Mario Demo:
Image


Downloads
JGE++ v0.2b
SkyAnimator v1.6b R2 (English version)
SkyAnimator v1.6b R2 (Chinese version)

Prebuilt binaries:

JGE++ Demo for PSP firmware 1.50
JGE++ Demo for Windows
SkyAnimator Demo for PSP firmware 1.50
SkyAnimator Demo for Windows
Mario Demo for PSP firmware 1.50
Mario Demo for Windows
StarBugz Prototype for PSP firmware 1.50
StarBugz Prototype for Windows


Known issues
- Wav files must be 8 bit mono.
- There is an extra "." in front of hge.lib in VC6 project settings of Demo's Debug build for Windows. Please remove it in order to build.
Last edited by dr_watson on Fri Mar 31, 2006 10:50 pm, edited 12 times in total.
dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

An introduction to rendering 2D images with GU

Post by dr_watson »

An introduction to rendering 2D images with GU

JGE++ uses the GU functions for rendering and this is an introduction on how the 2D rendering is done with this 3D library.

PSP has 2MB video RAM. Apart from using as frame buffers, user textures can also be stored here for faster GPU process. The pixel format that is chosen for the game will have a big impact on how many textures can be stored in the video RAM.

There are four different pixel formats available on PSP:

PSP_DISPLAY_PIXEL_FORMAT_565 //16-bit RGB 5:6:5
PSP_DISPLAY_PIXEL_FORMAT_5551 //16-bit RGBA 5:5:5:1
PSP_DISPLAY_PIXEL_FORMAT_4444 //16-bit RGBA 4:4:4:4
PSP_DISPLAY_PIXEL_FORMAT_8888 //32-bit RGBA 8:8:8:8

Since transparent colour is pretty much needed for all game applications, the 565 format is basically out. The 5551 and 4444 format both take 2 bytes for a single pixel. If effects such as alpha blending is required, then the 4444 format will be the choice to use.

Of course, the optimal option will be the 8888 format, which produce the maximum number of colours on screen. However this format uses 4 bytes for each pixel. A primary frame buffer plus a back buffer will take up 512x272x4x2 = 1,088KB. There will be only 960KB left for user textures. In that case, most of the textures will need to be stored in system RAM and thus will slow down all the rendering.

Here is the code segment on GU intialization:

sceGuInit();

sceGuStart(GU_DIRECT,list);
mVideoBufferStart = 0;

// setup frame buffer for rendering
sceGuDrawBuffer(BUFFER_FORMAT, (void *)mVideoBufferStart, FRAME_BUFFER_WIDTH);
mVideoBufferStart += FRAME_BUFFER_SIZE;

// setup frame buffer for displaying
sceGuDispBuffer(SCREEN_WIDTH, SCREEN_HEIGHT, (void *)mVideoBufferStart, FRAME_BUFFER_WIDTH);

// setup starting address of video RAM for user textures
mVideoBufferStart += FRAME_BUFFER_SIZE;
mCurrentPointer = mVideoBufferStart;

sceGuOffset(2048 - (SCREEN_WIDTH/2), 2048 - (SCREEN_HEIGHT/2));
sceGuViewport(2048, 2048, SCREEN_WIDTH, SCREEN_HEIGHT);

sceGuScissor(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
sceGuEnable(GU_SCISSOR_TEST);
sceGuFrontFace(GU_CW);
sceGuEnable(GU_TEXTURE_2D);
sceGuShadeModel(GU_SMOOTH);

// enable alpha blending
sceGuEnable(GU_BLEND);
sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0);

sceGuClear(GU_COLOR_BUFFER_BIT);
sceGuFinish();
sceGuSync(0,0);

sceDisplayWaitVblankStart();
sceGuDisplay(1);
To render a 2D image onto screen, a texture containing such image is loaded and a quad structure is defined to specify the area of the texture to render. Basically 2D images rendering with GU is done by rendering textured quads.

A quad consists of four vertices. The order of the vertices is shown below:

Code: Select all

v0---v1
 |  /|
 | / |
 |/  |
v2---v3
Here is the structure of Vertex:

Code: Select all

struct Vertex
{
       float u, v;
       PIXEL_TYPE color;
       float x, y, z;
};
(x,y) is the screen coordinates and (u,v) is the texture coordinates.

As an example, the first frame of the following animation will be shown at screen location (100,100). The size of each frame is 100x100:

Image

Here is the settings of the four vertices:

Code: Select all

vertices[0].u = 0.0f; 
vertices[0].v = 0.0f;
vertices[0].color = color;
vertices[0].x = 100.0f; 
vertices[0].y = 100.0f; 
vertices[0].z = 0.0f;

vertices[1].u = 100.0f; 
vertices[1].v = 0.0f;
vertices[1].color = color;
vertices[1].x = 200.0f; 
vertices[1].y = 100.0f; 
vertices[1].z = 0.0f;

vertices[2].u = 0.0f; 
vertices[2].v = 100.0f;
vertices[2].color = color;
vertices[2].x = 100.0f; 
vertices[2].y = 200.0f; 
vertices[2].z = 0.0f;

vertices[3].u = 100.0f 
vertices[3].v = 100.0f;
vertices[3].color = color;
vertices[3].x = 200.0f; 
vertices[3].y = 200.0f; 
vertices[3].z = 0.0f;
After setting up the vertices, GU function sceGuDrawArray will be used to render the quad:

Code: Select all

sceGuDrawArray(GU_TRIANGLE_STRIP,GU_TEXTURE_32BITF|TEXTURE_COLOR_FORMAT|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 4, 0, vertices);
Parameters of sceGuDrawArray:
GU_TRIANGLE_STRIP
- rendering triangles

GU_TEXTURE_32BITF|TEXTURE_COLOR_FORMAT|GU_VERTEX_32BITF|GU_TRANSFORM_2D:
- vertex structure is texture coordinates(floats), followed by colour, followed by screen coordinates(floats) with 2D transform.

4
- 4 vertices.

0
- starting index of vertices

vertices
- vertices
dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

Hello World for JGE++

Post by dr_watson »

Hello World for JGE++

The JGE++ package comes with a demo application called Demo. This is basically a Hello World program for JGE++.

When programming 2D games, in order to show an image on screen, the image is loaded and then a "DrawImage" function is used to do the job. Sometimes a few images are packed into a single one and portions of it are used for rendering in order to save file space, for easy management or for whatever reasons.

With hardware accelerated 2D game engines, this "packed" image approach has become a necessary because the width/height of the texture that is fed to the graphics hardware need to be in the power of 2. And also, switching from one texture to another may take some extra GPU cycles. Obviously the best way to do is to have a relative large texture, say 512x512, and putting all images in it and render portions of it for different sprites. In practice of course it is not required to have just one single texture for a whole game. But keeping the number of textures to a minimal is a good habit anyway!

Here is a sample texture (128x128) with a cartoon character and the text "HELLO WORLD":

Image

A quad structure is used to specify which area of the large texture is to be rendered. Here is an example on how to load a texture and render an image to screen in JGE++:

Code: Select all


// load texture
mTexture = mEngine->LoadTexture("Res/mario.png", true);	
// setup quad structure
mMario = new JQuad(mTexture, 0.0f, 0.0f, 62.0f, 72.0f);
// set center of quad
mMario->SetHotSpot(31.0f, 36.0f);

.
.
.
// render to screen
mEngine->RenderQuad(mMario, 80.0f, 80.0f);					

It may seem tedious to concatenate images together and define quads just to render a few images on screen, but the good thing about using hardware accelerated functions is that apart from plain rendering, it is possible to do scaling, rotation and alpha/colour blending at the same time and cost nothing to the main CPU. All these mean fast speed, hence, the term hardware accleration!

Here are some examples of how to do scaling, rotation and colour blending:

Code: Select all


// render with rotation
mEngine->RenderQuad(mMario, 80.0f, 200.0f, mAngle, 1.0f, 1.0f);

// set blending colour
mMario->SetColor(ARGB(128,255,255,0));
// render with colour blending and scaling
mEngine->RenderQuad(mMario, 380.0f, 150.0f, 0.0f, mScale, mScale);	
mMario->SetColor(ARGB(255,255,255,255));

Easy! Time to make some cool games!
Brunni
Posts: 186
Joined: Sat Oct 08, 2005 10:27 pm

Post by Brunni »

Cool ^^
Was it originally designed for Windows or PSP (or both at once)?
Sorry for my bad english
Image Oldschool library for PSP - PC version released
dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

Post by dr_watson »

It was written for PSP while I was making StarBugz. Since I borrowed lots of ideas from HGE, I knew I would make a kind of HGE wrapper to make JGE++ games run on Windows as well. It's really painful to debug programs on PSP directly. I made the Mario Demo almost entirely in M$ Windows. Occasionally I would put it on my PSP for some "real" testing ;)
User avatar
dot_blank
Posts: 498
Joined: Wed Sep 28, 2005 8:47 am
Location: Brasil

Post by dot_blank »

nice work :)
10011011 00101010 11010111 10001001 10111010
dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

Post by dr_watson »

SkyAnimator English version is available now:

SkyAnimator (English version)
Shapyi
Posts: 95
Joined: Mon Apr 25, 2005 9:31 am

Post by Shapyi »

Great work. I like the fact you included the source code so we can learn from it. I'm gonna check out the samples.
alain91
Posts: 13
Joined: Wed Mar 01, 2006 7:55 pm

hang

Post by alain91 »

Hello dr_watson,

It seems great but when I try to launch demo project, it hangs with a blue screen :) and registers dump ?
dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

Post by dr_watson »

Is it Windows build or PSP build?

For PSP, there's a "res" folder in the "bin" folder of each project. Did you put that on PSP together with your EBOOT?
ipsp
Posts: 26
Joined: Wed Feb 01, 2006 9:46 am
Location: Sydney

Post by ipsp »

Nice work.

I've had a quick look whilst I was at work yesterday, and I must say the examples gave some insight into it abilities, hence making it standout for other libraries.

I'll investigate this more once I finish my current project. Again nice work good to see more libararies added to the PSP community.
dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

Post by dr_watson »

alain91
Posts: 13
Joined: Wed Mar 01, 2006 7:55 pm

blue screen

Post by alain91 »

Hello dr_watson,

The problem was only on demo program. Mario & others work well.
subbie
Posts: 122
Joined: Thu May 05, 2005 4:14 am

Post by subbie »

Yo, just simple question. Why use GU_TRIANGLE_STRIP to render sprites? You can just use GU_SPRITES insted. You just need to suply the upper left & lower right verticies to form a quad.
dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

Post by dr_watson »

subbie wrote:Yo, just simple question. Why use GU_TRIANGLE_STRIP to render sprites? You can just use GU_SPRITES insted. You just need to suply the upper left & lower right verticies to form a quad.
yes, you can use GU_SPRITES... but you can't rotate with it ;)
alain91 wrote:The problem was only on demo program
Can you try the prebuilt Demo and see if that works?
alain91
Posts: 13
Joined: Wed Mar 01, 2006 7:55 pm

prebuilt demo

Post by alain91 »

dr_watson : The prebuit demo work well :)
dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

Post by dr_watson »

A new bug-fixed version of SkyAnimator is available for download and the URL is at the original post.
alain91
Posts: 13
Joined: Wed Mar 01, 2006 7:55 pm

scrolling & hge

Post by alain91 »

hello dr_watson,

I wondered how you would code a scrolling map with jge ?

- a big sprite where you put tiles in it ?
- a direct memory access ?
- ..?

Thanks a lot,
Alain
Brunni
Posts: 186
Joined: Sat Oct 08, 2005 10:27 pm

Post by Brunni »

You draw multiple sprites, each one corresponding to one tile.
Sorry for my bad english
Image Oldschool library for PSP - PC version released
alain91
Posts: 13
Joined: Wed Mar 01, 2006 7:55 pm

merci

Post by alain91 »

Thanks Brunni ;)

Just wondering if your lib is better than this...
dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

Post by dr_watson »

hi alain91, you can have a look of the Mario demo. It features parallax scrolling. The very front layer is a tile map while the other layers are just big images.

I reckon OSLib has more features but JGE++ offers M$ Windows' support, which makes it easier for the development ;)

However, from Brunni's posts I think he's aiming at Windows support too :)
alain91
Posts: 13
Joined: Wed Mar 01, 2006 7:55 pm

Post by alain91 »

Hello dr_watson,

Windows support for testing is a sure 'plus' :)

So you use sprites to build a map.. wouldn't it be faster and less ressources consuming to have a 'blit' functions (direct draw from tiles to memory) ?

Sorry if it is a stupid question, Brunni oslib seems to use the same system as you ..

Regards,
Alain
dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

Post by dr_watson »

Hi Alain,

By "draw from tiles to memory", do you mean you have a large image in memory for the background, you blit all tiles to that image to construct the background and then render that large image to screen?

If you are to use GU functions to render that large image, the size of it need to be within 512x512, which is the largest texture size GU supports. Anything larger than that will require you to play some tricks to render them properly.

Since GU functions are hardware accelerated, there's no problem to render few dozens of tile images at each frame for the tile map. For example, with that Mario Demo, you got 300-400 FPS. Not fast enough? ^^
Brunni
Posts: 186
Joined: Sat Oct 08, 2005 10:27 pm

Post by Brunni »

alain91> I don't think you can compare both libraries, it's up to you to test them to find the most adapted to you ;)
And to answer your question, direct memory blitting is not better than using "sprites", as they are hardware accelerated.
The advantage of using sprites lets you mix pixelformats (for example draw a 16-bit tilemap on a 32-bit drawbuffer) and is more flexible. You can for example enable transparency and then display your map => it will be transparent, and so on.
Sorry for my bad english
Image Oldschool library for PSP - PC version released
Panajev2001a
Posts: 100
Joined: Sat Aug 20, 2005 3:25 am

Post by Panajev2001a »

Brunni wrote:alain91> I don't think you can compare both libraries, it's up to you to test them to find the most adapted to you ;)
And to answer your question, direct memory blitting is not better than using "sprites", as they are hardware accelerated.
The advantage of using sprites lets you mix pixelformats (for example draw a 16-bit tilemap on a 32-bit drawbuffer) and is more flexible. You can for example enable transparency and then display your map => it will be transparent, and so on.
Brunni, does OSlib "emulates" also the GBA's BG Tile Modes map and amount of unique tiles limitations making it similar to how you would do things on the GBA or you only have a limitation on map size (1024x1024 maybe or 512x512 ?) ?
Brunni
Posts: 186
Joined: Sat Oct 08, 2005 10:27 pm

Post by Brunni »

Yes. The map size is not limited (unlike the GBA), but all tiles must fit in a single image (and its maximum size is 512x512, it's a limitation of the PSP GPU).
Sorry for my bad english
Image Oldschool library for PSP - PC version released
Panajev2001a
Posts: 100
Joined: Sat Aug 20, 2005 3:25 am

Post by Panajev2001a »

Brunni wrote:Yes. The map size is not limited (unlike the GBA), but all tiles must fit in a single image (and its maximum size is 512x512, it's a limitation of the PSP GPU).
So basically you have an unlimited map size, but effectively the map can only have 4096 unique tiles (which is (512*512) / (8*8)), am I correct (assuming tile size is 8*8 of course) ?

At least it simplifies the work a bit... there's only the need to find out how to dynamically update the tile set for the BG map and it should work out quite well.
subbie
Posts: 122
Joined: Thu May 05, 2005 4:14 am

Post by subbie »

dr_watson wrote:
subbie wrote:Yo, just simple question. Why use GU_TRIANGLE_STRIP to render sprites? You can just use GU_SPRITES insted. You just need to suply the upper left & lower right verticies to form a quad.
yes, you can use GU_SPRITES... but you can't rotate with it ;)
In which sense. sceGumRotateX/Y/Z ?


Could also just manualy rotate your verticies (only 2) yourself. The benifit is you're only sending 2 verts though the pipeline vs 4.
dr_watson
Posts: 42
Joined: Mon Nov 28, 2005 11:30 am

Post by dr_watson »

subbie wrote:
In which sense. sceGumRotateX/Y/Z ?

Could also just manualy rotate your verticies (only 2) yourself. The benifit is you're only sending 2 verts though the pipeline vs 4.
I've tried rotating vertices manually with GU_SPRITES but it didn't work. It makes sense if you think about it as by manually rotating 2 vertices, you are basically changing the locations of these 2 vertices only. These 2 vertices are the 2 corners of a GU_SPRITE so this "rotation" only changes the SIZE of the SPRITE rather than rotates it.

With 2D images, we are using GU_TRANSFORM_2D rather than GU_TRANSFORM_3D. I think sceGumRotateX/Y/Z may not work. I'm not a GU expert so I guess someone else may have a better answer for this question.
subbie
Posts: 122
Joined: Thu May 05, 2005 4:14 am

Post by subbie »

dr_watson wrote:
subbie wrote:
In which sense. sceGumRotateX/Y/Z ?

Could also just manualy rotate your verticies (only 2) yourself. The benifit is you're only sending 2 verts though the pipeline vs 4.
I've tried rotating vertices manually with GU_SPRITES but it didn't work. It makes sense if you think about it as by manually rotating 2 vertices, you are basically changing the locations of these 2 vertices only. These 2 vertices are the 2 corners of a GU_SPRITE so this "rotation" only changes the SIZE of the SPRITE rather than rotates it.

With 2D images, we are using GU_TRANSFORM_2D rather than GU_TRANSFORM_3D. I think sceGumRotateX/Y/Z may not work. I'm not a GU expert so I guess someone else may have a better answer for this question.
Ah I see. That might be why.
Could always just do an Ortho projection and transform in 3D. It could lead to many advantages. Since Transform_2d just passes evertything to the rasterizer vs transforming then passing along.
Post Reply