View Single Post
 
Old 03-28-2007, 09:26 PM
PSdonkey's Avatar
PSdonkey PSdonkey is offline
Squirrel Admin
PSP Titan
 
Join Date: Mar 2006
Posts: 9,117
PSdonkey has a reputation beyond reputePSdonkey has a reputation beyond reputePSdonkey has a reputation beyond reputePSdonkey has a reputation beyond reputePSdonkey has a reputation beyond reputePSdonkey has a reputation beyond reputePSdonkey has a reputation beyond reputePSdonkey has a reputation beyond reputePSdonkey has a reputation beyond reputePSdonkey has a reputation beyond reputePSdonkey has a reputation beyond repute
Default

Lesson 6 - Map Time!

Here is the lesson that a lot of you have been waiting for, Maps. In this lesson, I will show you how to convert a large 1024x1024 image into a scaling map that can be scrolled in any direction. I will post and explain the source code for this project and I will post the source code which will use the map we created and combine lesson 4 sprite animations to show a character moving along the map we created with basic border collision so the character doesn't run off the screen.
I strongly suggest that you go through my previous lessons before you decide to tackle this lesson as a lot of the functions in the source code have already been explained in the previous lessons.


Background information - The PSP can not load any image larger than 512x512. That does not leave much room for a map since the PSP's screen resolution is already 480x272.
We can however convert an image 1024x1024 (or greater) into an image that is 512x512 using a program I found.

Program? What program?
Back probably before most of your time, a lot of programmers were into making homebrew for the GameBoy Advance. This was of course before the PSP even was designed. So a programmer came up with a map converter for the GBA which would allow coders to create large 2D maps for their homebrew game that would fit on the GBA's screen. The program is called GBA map converter.exe Fortunately for us, this program works well with OSlib.



Here is the 1024x1024 png image that we are going to convert to 512x512 so that it loads into the PSP.



Notice how there is a pink border at the top of the map image. We need that to wrap the image together once it loads in the PSP since we are going to loop the map on the PSP's screen in all directions for infinity. The pink border will not show up on the PSP's screen as you should know by now if you followed my previous lessons. So now the map is actually 1024x1060 in size as I added a 16 pixels border at the top of the image.
Note - You can convert any size image for usage as a map for the PSP. It doesn't have to be 1024x1024. It can be 1024x272 if you would like so that the map only scrolls left and right and not up and down.

The Map converter program and the source files of both programs and the compiled EBOOTs can be found at the bottom of this post in the download link.




First I will explain how to use the Map converter program. (This is just a simple quick guide as there is already a large help file included in the download link along with the program.)

Have your map image ready for converting. (Mine is called Ocean.png so that is what I will use for this example.)
Double click the program and you will see a button on the right that says source file.
Click on the source file button to locate the map you want to convert.
Then on the bottom where it says "optimal tileset" click on 16x16.
Then on colors to the right click on 32 bit.
Then under "Destination for the map", change the name to Ocean.h
Now on the bottom, click on "ok".
Now on the top left of the program you should see "+Tilesets", click on the positive sign and you should see the name of your map right under it. (Mine is called Ocean so you should see Ocean.)
Click on your map name Ocean and on the right you should see a button called "Options".
Click on that and change the value to 512.
Now on top of your program goto Edit and click on "Export image".
Now save your map image as tileset.png and click ok.
You can exit the program because now you are done. The program should have created 3 files for you: Ocean.h, tileset.png and some other file called Ocean.til.c (You can ignore the last one as you only need tileset.png and Ocean.h for your program)
Now there are many different options for you to use with this program. This is just he basics that I have given you for our lesson example. (Read through the help file and learn what much more you can do with this program.)

For images smaller then 512x512

Gunner154 has made a very nice visual tutorial on how to use the Map converter for images on your PSP that are less than 512x512. Here is his tutorial which you can also follow along for images larger than 512x512. Here is what he wrote:

Quote:
Originally Posted by Gunner154
Hi, I have had problems with Maps.h and would like to share how to fix the image problems. I would like to thank PSDonkey for alot of help with this!

NOTE: TRY AND RE-SIZE ALL YOUR IMAGES YOUR GOING TO USE TO 480x272

1) Open "GBA Convertor.exe" and click "Browse" thats at the end of the "Source file" text bar.



2) Find your image and open it.
3) Make "Colors" = "32 bits (RGBA)" and Optimized tileset = "16x16", Click "Ok!"


4) Under "Tilesets" their should be a tab named as your image file. Click on it.


5) Click on "Options" and make its "Width" = "512".


6) Click "Edit > Export (image)" (Ctrl+X), Now save the image as "FileName.png" or what ever you want ".png".


7) Open "Ocean.map.c", You should see somthing named "Ocean_map[65][64] = {" remember those numbers (65,64).


8) Rename "Ocean.map.c" too "Maps.h" or somthing ".h".


9) Open "main.c" and type #include "Ocean.h" (With Quotes).


10) Now Add


Code:
Ocean = oslCreateMap(
		Ocean_tileset, //The Thing You Defined As The Image
		Ocean_map, //The Thing In maps.h
		16,16, //Tileset 16x16 In GBA Convertor
		64,65, //Remember These Numbers?, See How Its 64,65 Instead Of 65,64?
		OSL_MF_U16); //This Stays As It Is!
11) Save "main.c" And Compile!

Download GBA Convertor
http://www.mediafire.com/?2na14z4nyym

Thank You!
Here is the Makefile:
Code:
TARGET = Donkey_Lesson6
OBJS = main.o 	

INCDIR = 
CFLAGS = -G4 -Wall -O2 
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

LIBDIR =
LDFLAGS =
STDLIBS= -losl -lpng -lz \
		-lpspsdk -lpspctrl -lpspumd -lpsprtc -lpsppower -lpspgu -lpspaudiolib -lpspaudio -lm
LIBS=$(STDLIBS)$(YOURLIBS)


EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Donkey_Lesson6

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
Here is the first source code for the basic map drawing:

Code:
//OSlib header file
#include <oslib/oslib.h>

//Include the Data part of the map
#include "Ocean.h"

//Necessary to create eboot
PSP_MODULE_INFO("OSLib Sample", 0, 1, 1);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);

//declaration of the pointers of our images
OSL_IMAGE *Ocean_tileset;

//declaration of the pointers of our Map
OSL_MAP *Ocean;

//variables
int i;

int main()
{
	//Initialization of the Oslib library
	oslInit(0);

	//Initialization of the graphics mode
	oslInitGfx(OSL_PF_8888, 1);

	//loads our images into memory
	Ocean_tileset = oslLoadImageFile("tileset.png", OSL_IN_RAM, OSL_PF_5551);
	
	//verification that all files are present
	if (!Ocean_tileset)
		oslDebug("It is impossible to load one or more of the images that are required in this program. Please make sure you have all the files required in the eboot folder");

	//configuration of the Map
	Ocean = oslCreateMap(
		Ocean_tileset,						//Tileset
		Ocean_map,							//Map
		16,16,								//Size of the tiles
		64,65,								//Size of the Map Map
		OSL_MF_U16);						//Format of the Map


	//main while loop
	while (!osl_quit)
	{
		//To be able to draw on the screen
		oslStartDrawing();

		//Clear the screen
		oslCls();

		//initiate the PSP's buttons
		oslReadKeys();
              
                //Map movement
		if (osl_keys->held.down)
	        {
		Ocean->scrollY += 2;
                }

			if (osl_keys->held.up)
	        {
                Ocean->scrollY -= 2;
                }

			if (osl_keys->held.right)
	        {
                Ocean->scrollX += 2;
                }

			if (osl_keys->held.left)
	        {
                Ocean->scrollX -= 2;
                }
		
		//Draws the Map on the screen
		oslDrawMapSimple(Ocean);
		
		//Ends drawing mode
		oslEndDrawing();

		//Synchronizes the screen
		oslSyncFrame();		
	}
	
	//Terminate the program
	oslEndGfx();
	oslQuit();
	return 0;
}
Source code explanation:

1) #include "Ocean.h"
This is the header file that our map converter created for us. We need to include this file in our program.

2) OSL_IMAGE *Ocean_tileset;
This is the name that we will give our tileset.png image that the program created for us. Remember, this is really tileset.png which is the new converted map from Ocean.png

3) OSL_MAP *Ocean;
This will be the name of our map as we use a pointer for it in our program.

4) Ocean_tileset = oslLoadImageFile("tileset.png", OSL_IN_RAM, OSL_PF_5551);
Look at #2. We are renaming our tileset.png that the program converted for us into the name Ocean_tileset

5) Ocean = oslCreateMap(
Ocean_tileset, //Tileset
Ocean_map, //Map
16,16, //Size of the tiles
64,65, //Size of the Map Map
OSL_MF_U16);

This is OSlib's way of creating the map. You will need to open Ocean.h up to understand some of these parameters.
The first parameter, Ocean_tileset, is the name of our image that was converted using the map converter program. (look more at explanation #2 and #4.)
The second parameter, Ocean_map is the name that is used in the Ocean.h file. Take a look at this line in Ocean.h
const unsigned short Ocean_map[65][64]
The second parameter is the name right before[65][64].
The third parameter 16,16 is the size of the tileset option we choose in our map converter program.
The fourth parameter, 64,65 is the numbers after Ocean_map in our Ocean.h file.
const unsigned short Ocean_map[65][64]
Notice how you need to switch the numbers from 65,64 to 64,65 in your source code.
The fifth parameter, OSL_MF_U16); is just the format of our map under OSlib. You do not need to worry about that as you will never change that parameter.

6) if (osl_keys->held.down)
{
Ocean->scrollY += 2;
}

This is the map's movement. Since the name of our map is Ocean, we use that name to scroll the map. If the down button is held down, the map will scroll down and the speed of every 2 pixels.

7) oslDrawMapSimple(Ocean);
This function simply draws our map which is named Ocean on our screen.


Here is the source code for the more advance map code which combines lesson's 4 sprite animation with this lesson and adds basic border collision. I also added the function
oslShowPSPHacksLogo(); which is used to show a PSP-Hacks homebrew competition splash screen and also the function
if (osl_keys->pressed.select)
oslWriteImageFilePNG(OSL_SECONDARY_BUFFER, "screenshot.png", 0);
which is used to take a screenshot of the current display on your PSP's screen.

Code:
//OSlib header file
#include <oslib/oslib.h>

//Include the Data part of the map
#include "Ocean.h"

//Necessary to create eboot
PSP_MODULE_INFO("OSLib Sample", 0, 1, 1);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);

//declaration of the pointers of our images
OSL_IMAGE *sprite, *Ocean_tileset;

//declaration of the pointers of our Map
OSL_MAP *Ocean;

//definitions
#define DOWN   0
#define UP     35
#define RIGHT  70
#define LEFT   105

//variables
int sprite_position;
int sprite_march;
int i;


//function declarations
void Buttons();
void SpriteAnimate();

int main()
{
	//Initialization of the Oslib library
	oslInit(0);

	//Initialization of the graphics mode
	oslInitGfx(OSL_PF_8888, 1);

        //Shows the psp-hacks hombrew competition splash screen
        oslShowPSPHacksLogo();

	//Sets the transparency color (pink)
	oslSetTransparentColor(RGB(255,0,255));

	//loads our images into memory
        Ocean_tileset = oslLoadImageFile("tileset.png", OSL_IN_RAM, OSL_PF_5551);
	sprite = oslLoadImageFile("sprite.png", OSL_IN_RAM, OSL_PF_5551);

	//Disables the transpaent color (pink)
	oslDisableTransparentColor();

	//verification that all files are present
	if (!sprite || !Ocean_tileset)
		oslDebug("It is impossible to load one or more of the images that are required in this program. Please make sure you have all the files required in the eboot folder");

//configuration of the Map
	    Ocean = oslCreateMap(
		Ocean_tileset,						//Tileset
		Ocean_map,							//Map
		16,16,								//Size of the tiles
		64,65,								//Size of the Map
		OSL_MF_U16);						//Format of the Map

        //Sets the sprite's original position on the screen
	sprite->x = 155;
	sprite->y = 95;
	sprite_position = DOWN;

	//main while loop
	while (!osl_quit)
	{
		//To be able to draw on the screen
		oslStartDrawing();		
		
		//calls the Buttons() function
		Buttons();

                //Draws the Map on the screen
		oslDrawMapSimple(Ocean);	

		//Draw the images to the screen
		oslDrawImage(sprite);

		//Ends drawing mode
		oslEndDrawing();

		//Synchronizes the screen
		oslSyncFrame();		
	}
	
	//Terminate the program
	oslEndGfx();
	oslQuit();
	return 0;
}


void Buttons()
{
	//initiate the PSP's buttons
	oslReadKeys();
   
     //Takes a screenshot of the PSP's screen 
     if (osl_keys->pressed.select)
    oslWriteImageFilePNG(OSL_SECONDARY_BUFFER, "screenshot.png", 0);

//Basic border collision
if (sprite->x <= 0)
 sprite->x = 0;

if (sprite->y <= 0)
 sprite->y = 0;

if (sprite->x >= 460)
 sprite->x = 460;

if (sprite->y >= 239)
 sprite->y = 239;

if (osl_keys->held.down)
	{
		Ocean->scrollY += 8;
		sprite->y += 1;
		sprite_position = DOWN;
		SpriteAnimate();
	}

	if (osl_keys->held.up)
	{
        Ocean->scrollY -= 8;
		sprite->y -= 1;
		sprite_position = UP;
		SpriteAnimate();
	}
	
	if (osl_keys->held.right)
	{
        Ocean->scrollX += 8;
		sprite->x += 1;
		sprite_position = RIGHT;
		SpriteAnimate();
	}
        if (osl_keys->held.left)
	{
        Ocean->scrollX -= 8;
		sprite->x -= 1;
		sprite_position = LEFT;
		SpriteAnimate();
	}
		
	

	//If a button is not pressed
	if (!osl_keys->held.value) 
	{
	//Start the variable over for when a button is pressed again
		sprite_march = 0; 

		//Sets the sprite's direction
		oslSetImageTileSize(sprite,0,sprite_position,22,35);
	}
}




void SpriteAnimate()
   {	
		//Moves the sprite in the row that it is in
		sprite_march++;


		//Moves the sprite constantly with no static position
		oslSetImageTileSize(sprite,(sprite_march * 22),sprite_position,22,35);

		//resets the sprite movement in that row
		if (sprite_march == 6) sprite_march = 0;
	
}
Some explanations:

1) oslShowPSPHacksLogo();
I added this function to OSlib so that those wanting to enter our homebrew comeptition can easily have a way to display one of our splash screens in their program. Simply create a folder called "psphacks" next to your eboot and inside that folder place the splash screen of your choice (must be in png format) and rename the splash screen to "psphacks-splash.png"
Once your program loads, the splash screen of your choice will display in your program.

2) if (sprite->x <= 0)
sprite->x = 0;

if (sprite->y <= 0)
sprite->y = 0;

if (sprite->x >= 460)
sprite->x = 460;

if (sprite->y >= 239)
sprite->y = 239;

This is the basic border collision detection I added to the program. The PSP's screen resolution is 480x272 pixels. So if we don't want our sprite image to move off the PSP's screen, we need to create imaginary borders for our image. The PSP's screen is measured in pixels coordinates x,y. The very top part of the PSP's screen is 0,0 and the bottom left of the screen is 0,272 and the top right of the PSP's screen is 480,0 and the bottom right of the PSP's screen is 480,272
if (sprite->x <= 0)
sprite->x = 0;

So if any of of image hits any part of our x coordinate which is less than 0 which means he would be moving of the left part of the screen in a negative direction, then we would reset his x coordinate to be 0 which means he can never try to move past the left part of the screen. This is the same for the other 3 if statements. x coordinates is for left and right and y coordinates is for up and down. Notice how we use 460 and 239 for the right and bottom coordinates instead of 480 and 272 which is the screens pixel length. The reason for that being is that the image is 22x32 pixels in dimension and the program measures the image by the very top left of the image at 0,0. So we need to take some of the 480 and 272 pixels off to match the image;s height and width or the image will look like it is still going past the right and bottom parts of the screen.

3) if (osl_keys->pressed.select)
oslWriteImageFilePNG(OSL_SECONDARY_BUFFER, "screenshot.png", 0);

If you press the select button using this function, it will write a screenshot image in the same folder where your EBOOT is located under the filename screenshot.png


Here is the download link for the map converter program along with the source files for both of the map programs and the compiled eboots as well.

http://www.mediafire.com/?ctwlmzig2vw

Sorry about not making this lesson as detailed as I wanted to because I have so much work to do, this is all the time I had to explain this map lesson. Maybe when I get some more time, I will come back to this post and add more details and explanations.
__________________
Want to become a PSP Dev the easy way? Check out my tutorial for the PSP here www.psp-hacks.com/forums/viewtopic.php?id=65403
Want to learn how to create your own games on the PSP? Check out my tutorial here http://www.psp-hacks.com/forums/view...693884#p693884
Want to learn how to program C++ ? Check out that tutorial here www.psp-hacks.com/forums/viewtopic.php?id=28694
Reply With Quote