Hello,
I'm trying to make a simple scrollable background.
I'm quite confused on how to accomplish this. There seems to be two ways to manage a background:
1) Load a single TIM file representing the whole "world" and generate a GsSPRITE from the resulting GsIMAGE. I should manually manage the number of "tpage"of the sprite. Am I able to scroll a background created like this? How do I change the [u,v] values of the GsSPRITE when I "cross" from one texture page to another? Possibly this is the efficient solution if the background size is under the screen limits and I don't need to scroll?
2) Create a tileset of GsCELL items, build a GsMAP and put it in a GsBG. This is easily scrollable but I don't know if it's the right thing when I have a background that is a big landscape image (that's the idea).
How do I create a tileset map and "position" all the items in the right place? Orion_ does it in his tutorial but the map looks to be an opaque object, I don't understand how to create such a map object.
Please could anyone amend my statements and hopefully clear things up a bit for me (in the meanwhile I'll keep on RTFM...)?
I hope I could explain the matter clear enough.
thanks
Scrollable background: how?
-
inc^lightforce Verified
- Psy-Q Enthusiast
- Posts: 248
- Joined: Mar 07, 2013
- I am a: Programmer Windows+PS1, GFX Artist
- PlayStation Model: Black
- Location: Germany
the rectangle code can be replaced with your background image.
feel free to use my code
Also give a Try to this MapBuilder: http://rapidshare.com/share/34A2D16781A ... DA7F10C6CB
HERE: CODING RECTANGLE & LINES with Code...
Grab all Files incl. a Demo for PS1 EMU here
have Fun while Coding. Questions? ASK .
inc.
feel free to use my code
Also give a Try to this MapBuilder: http://rapidshare.com/share/34A2D16781A ... DA7F10C6CB
HERE: CODING RECTANGLE & LINES with Code...
Grab all Files incl. a Demo for PS1 EMU here
Code: Select all
//***************************************************************
// THIS WAS OUR LOADER FOR Medal of Honor 2 - Underground PAL
// ===========================================================
// Many Lines i removed !!!
// Original Source: 27/10/2000
//
//***************************************************************
//--------------------------------------------------------------------------
// I N C L U D E S
//--------------------------------------------------------------------------
#include <sys/types.h>
#include <stdlib.h>
#include <libetc.h>
#include <libgte.h>
#include <libgpu.h>
#include <libgs.h>
#include <libsnd.h>
#include <libmath.h>
#include <libspu.h>
#include "hitmod.h" // For Sound
#include "pad.h" // PAD
#include "sinuss.h" // Sinus made with Sinuslab by Hitmen
#include "Sinstuff.h" // Sinus made with Sinuslab by Hitmen
#define MAXCHAR 42
#define DEVELOPEMENT
#define ORDERING_TABLE_LENGTH (5)
#define MAX_NO_PACKETS (3000)
#define rnd(max) ((rand()*(max))/(32768)+1)
//--------------------------------------------------------------------------
// G L O B A L S
//--------------------------------------------------------------------------
GsOT othWorld[2];
GsOT_TAG otWorld[2][1<<ORDERING_TABLE_LENGTH];
PACKET out_packet[2][(MAX_NO_PACKETS * 24)];
int currentBuffer;
u_long PADstatus=0; // Save PAD STATUS
int v_countGFX=0, v_countCODE=0; // HSync Counter
u_char HZMode=MODE_NTSC;
int Xangle,Yangle,depth;
int Xangle2,Yangle2;
int iScrollOffset=0;
extern char shades[]; // sound file
//-------------------------
// Font-Sprites & Textures
//-------------------------
GsBOXF mybox[6]; // 2D RECTANGLE
GsLINE line[360];
GsGLINE line2[4];
int Video_MODE=0;
//--------------------------------------------------------------------------
// P R O T O T Y P E S
//--------------------------------------------------------------------------
void InitialiseGraphics(int,int,int); // Width, Height, MODE
void UpdateWorld();
void RenderWorld(char cClear);
void LoadTIMData (u_long *tMemAddress); // RAM -> VRam
void SetSpriteInfo(GsSPRITE *tSprite, u_long tMemAddress, long tX, long tY, int tCut);
void init_line(void);
void do_line(void); // INIT LINE
void do_bar(void); // INIT RECTANGLE
void init_bar(void); // INIT RECTANGLE
void init_Kloetze(void); // 2D RECTANGLE
int sin1=0;
int sin2=0;
int main()
{
u_long lTmp1;
int i,j,k;
int temp,temp1;
int iTmp1,iTmp2,iTmp3,iTmp4;
iTmp1=-60;
iTmp2=-280;
iTmp3=320;
iTmp4=500;
Xangle=Yangle=1; //init x angle and y angle
PadInit(0); // Joypad Init
// CHECKS AUTO REGION , INPUT VALUES FOR PAL or NTSC PATCH HERE
if (*(char *)0xbfc7ff52=='E') // E(urope) --> PAL; A(merica) and J(apan) both use NTSC
{
HZMode=MODE_PAL;
}
else
{
HZMode=MODE_NTSC;
}
InitialiseGraphics(320,240,HZMode); // GFX Init, inkl. Init akt. Buffer...
MOD_Init(); // Sound Check
MOD_Load((u_char *) shades); // load Sound
MOD_Start(); // play Sound
init_line(); // INIT LINE
init_bar(); // 2D RECTANGLE
init_Kloetze(); // 2D RECTANGLE
for (i=0;i<140;i++)
// ------------------------------------
// -------- M A I N --------
// ------------------------------------
while(1)
{
PADstatus=PadRead(4);
if(PADstatus&Pad1x){Video_MODE=1; break; }
if(PADstatus&Pad1crc){Video_MODE=2; break; }
do_line(); // GO FOR LINE
do_bar(); // GO FOR RECTANGLE
// Define RECTANGLE MOVEMENT
iTmp1+=1;
iTmp2+=1;
iTmp3-=1;
iTmp4-=1;
if(iTmp1>320) iTmp1=-50;
if(iTmp2>320) iTmp2=iTmp1-200;
if(iTmp3<-150) iTmp3=320;
if(iTmp4<-150) iTmp4=iTmp3+190;
mybox[0].x=iTmp1;
mybox[1].x=iTmp2;
mybox[2].x=iTmp2+40;
mybox[3].x=iTmp3;
mybox[4].x=iTmp4;
mybox[5].x=iTmp4;
GsSortBoxFill(&mybox[0],&othWorld[currentBuffer],2);
GsSortBoxFill(&mybox[1],&othWorld[currentBuffer],2);
GsSortBoxFill(&mybox[2],&othWorld[currentBuffer],2);
GsSortBoxFill(&mybox[3],&othWorld[currentBuffer],2);
GsSortBoxFill(&mybox[4],&othWorld[currentBuffer],2);
GsSortBoxFill(&mybox[5],&othWorld[currentBuffer],2);
RenderWorld(60);
}
// ======================================================
// NOT IMPORTANT. THIS IS THE REST, A SNIPPET OF OUR CRACKS
// ======================================================
SpuInit();
SpuQuit();
MOD_Stop();
MOD_Free();
//VSync(3);
PadStop();
ResetGraph(0);
StopCallback();
// ======================================================
// ===============================================
}
void InitialiseGraphics(int SCRWidth,int SCRHeight,int HZMode)
{
SetVideoMode(HZMode);
if ((HZMode == MODE_NTSC) && (SCRHeight==256)) SCRHeight=240;
GsInitGraph(SCRWidth, SCRHeight, GsNONINTER|GsOFSGPU, 0, 0);
GsDefDispBuff(0, 0, 0, SCRHeight);
// Correct Error in Library
if (SCRHeight == 256) GsDISPENV.screen.h=256;
othWorld[0].length = ORDERING_TABLE_LENGTH;
othWorld[1].length = ORDERING_TABLE_LENGTH;
othWorld[0].org = otWorld[0];
othWorld[1].org = otWorld[1];
GsClearOt(0,0,&othWorld[0]);
GsClearOt(0,0,&othWorld[1]);
// Get the current Buffer
currentBuffer=GsGetActiveBuff();
// set Address for Packet
GsSetWorkBase((PACKET*)out_packet[currentBuffer]);
}
void RenderWorld(char cClear)
{
// ------------------------------------ " AN OLD LIST"
v_countCODE=VSync(1);
DrawSync(0);
v_countGFX = VSync(1);
VSync(0); // wait until GPU are finished OLD LIST
// swap both Buffers (Display / Drawing)
GsSwapDispBuff();
// ------------------------------------ "ACTUAL LIST"
// "Register" a "ClearScreen"- Command in OT
// R, G, B
if (cClear==1) GsSortClear(0, 0, 0,&othWorld[currentBuffer]); // here can be changed the screen background Color
if (cClear==60) GsSortClear(78, 0, 92,&othWorld[currentBuffer]); // here can be changed the screen background Color
if (cClear==255) GsSortClear(255, 255, 255,&othWorld[currentBuffer]); // here can be changed the screen background Color
// start drawing ( GPU is now drawing the OT in Background)
GsDrawOt(&othWorld[currentBuffer]);
FntFlush(-1);
// ------------------------------------ "NEW LIST"
// init next OT !!!
// get the actual Buffer
currentBuffer=GsGetActiveBuff();
// set Address for Packets
GsSetWorkBase((PACKET*)out_packet[currentBuffer]);
// erase Content of OT
GsClearOt(0, 0, &othWorld[currentBuffer]);
// OT is now ready for new OT Commands
}
void LoadTIMData(u_long *tMemAddress)
{
RECT tRect;
GsIMAGE tTim;
DrawSync(0);
tMemAddress++;
GsGetTimInfo(tMemAddress, &tTim); // SAVE TIM-Information to tTim
tRect.x = tTim.px;
tRect.y = tTim.py;
tRect.w = tTim.pw;
tRect.h = tTim.ph;
LoadImage(&tRect, tTim.pixel); // Load TIM-Data in VideoRam
DrawSync(0);
if ((tTim.pmode >> 3) & 0x01)
{
tRect.x = tTim.cx;
tRect.y = tTim.cy;
tRect.w = tTim.cw;
tRect.h = tTim.ch;
LoadImage(&tRect, tTim.clut); // load CLUT in VideoRam
};
DrawSync(0); // wait until GPU is ready
}
void SetSpriteInfo(GsSPRITE *tSprite, u_long tMemAddress, long tX, long tY, int tCut)
{
GsIMAGE tTim; // TIM image Information
tMemAddress += 4; // Pointer to Data
GsGetTimInfo((u_long *) tMemAddress, &tTim); // get TIM Information in tTim
tSprite->x = tX; // set Cordinates
tSprite->y = tY; // set Cordinates
switch (tTim.pmode & 3) // X-Value depends on BitDepht
{
case 0: tSprite->w = tTim.pw << 2;
tSprite->u = (tTim.px & 0x3f) * 4;
break;
case 1: tSprite->w = tTim.pw << 1;
tSprite->u = (tTim.px & 0x3f) * 2;
break;
default: tSprite->w = tTim.pw;
tSprite->u = tTim.px & 0x3f;
};
tSprite->h = tTim.ph;
tSprite->v = tTim.py & 0xff;
tSprite->tpage = GetTPage((tTim.pmode & 3),0,tTim.px,tTim.py);
tSprite->attribute = (tTim.pmode & 3) << 24;
tSprite->cx = tTim.cx; // set CLUT of Sprite
tSprite->cy = tTim.cy;
tSprite->r = tSprite->g = tSprite->b = 128; // Colour intensity
// set to Standart
tSprite->mx = tSprite->w/2; // Ref-POINT to the CENTER of a Sprite
tSprite->my = tSprite->h/2;
tSprite->scalex = tSprite->scaley = ONE; // Scale to 1 (real Size)
tSprite->rotate = 0; // rotation angle to 0 ZERO
if (tCut) // Cut Sprite if a Sprite have an illegal size
tSprite->w -= tCut;
};
//===============================================
// REGISTER ALL LINES (position + rgb)
//===============================================
void init_line()
{
line2[0].x0=0;
line2[0].y0=65;
line2[0].x1=160;
line2[0].y1=65;
line2[2].x0=160;
line2[2].y0=65;
line2[2].x1=320;
line2[2].y1=65;
line2[1].x0=0;
line2[1].y0=179;
line2[1].x1=160;
line2[1].y1=179;
line2[3].x0=160;
line2[3].y0=179;
line2[3].x1=320;
line2[3].y1=179;
}
//======================================================
// DRAW THE LINES
//======================================================
void do_line()
{
GsSortGLine(&line2[0],&othWorld[currentBuffer],3);
line2[0].r0=78;
line2[0].g0=0;
line2[0].b0=92;
line2[0].r1=255;
line2[0].g1=255;
line2[0].b1=255;
GsSortGLine(&line2[2],&othWorld[currentBuffer],3);
line2[2].r0=255;
line2[2].g0=255;
line2[2].b0=255;
line2[2].r1=78;
line2[2].g1=0;
line2[2].b1=92;
GsSortGLine(&line2[1],&othWorld[currentBuffer],3);
line2[1].r0=78;
line2[1].g0=0;
line2[1].b0=92;
line2[1].r1=255;
line2[1].g1=255;
line2[1].b1=255;
GsSortGLine(&line2[3],&othWorld[currentBuffer],3);
line2[3].r0=255;
line2[3].g0=255;
line2[3].b0=255;
line2[3].r1=78;
line2[3].g1=0;
line2[3].b1=92;
}
void do_bar()
{
int i,j;
if(sin1>=359) sin1=0;
sin2=sin1=sin1+1;
for(i=0;i<359;i++)
{
j=i+1;
line[i].attribute=(1<<28)+(1<<27)+(2<<24)+(0<<28)+(1<<30);
line[i].r=32;
line[i].g=0;
line[i].b=41;
line[i].x0=150;
line[i].x1=165+(scalesin[j]+scalesin2[sin2]/2);
line[i].y0=120;
line[i].y1=120+(scalesin2[j]/2);
GsSortLine(&line[i],&othWorld[currentBuffer],3);
sin2+=2;
if(sin2>=360) sin2-=360;
}
}
void init_bar()
{
int k;
for(k=0;k<360;k++)
{
line[k]=line[0];
line[k].y0=60;
line[k].y1=100;
line[k].r=line[k].b=line[k].g=128;
}
}
void init_Kloetze() // 2D RECTANGLE
{int iTmp1,iTmp2,iTmp3,iTmp4;
iTmp1=-60;
iTmp2=-280;
iTmp3=320;
iTmp4=500;
mybox[0].w=31;
mybox[0].h=24;
mybox[0].y=10;
mybox[0].r=104;mybox[0].g=0;mybox[0].b=122;
mybox[1].w=76;
mybox[1].h=20;
mybox[1].y=45;
mybox[1].r=104;mybox[1].g=0;mybox[1].b=122;
mybox[2].w=20;
mybox[2].h=55;
mybox[2].y=5;
mybox[2].r=104;mybox[2].g=0;mybox[2].b=122;
mybox[3].w=56;
mybox[3].h=51;
mybox[3].y=180;
mybox[3].r=104;mybox[3].g=0;mybox[3].b=122;
mybox[4].w=20;
mybox[4].h=58;
mybox[4].y=180;
mybox[4].r=104;mybox[4].g=0;mybox[4].b=122;
mybox[5].w=135;
mybox[5].h=20;
mybox[5].y=206;
mybox[5].r=104;mybox[5].g=0;mybox[5].b=122;
}
inc.
Last edited by inc^lightforce on November 8th, 2013, 6:13 am, edited 1 time in total.
just stopped by to say thank you. Hope I'll have time this weekend to check your examples.inc^lightforce wrote:the rectangle code can be replaced with yout background image.
feel free to use my code
The background now is ok, but when I send to the framebuffer (GsSortSprite) another sprite I have a second "ghost" sprite appearing at [0,0]. This does not happen without background.
I need to go back to the blackboard and study the ordering tables usage better. I'm surely mixing up something with the priority or I'm not invoking DrawSync() at the right moment.
Who is online
Users browsing this forum: No registered users and 6 guests