#include "header.h" u_short particleClutX[MAX_PARTICLE_TYPES], particleClutY[MAX_PARTICLE_TYPES]; u_char particleNum=0; GsSPRITE particleSprite; int partStart, partEnd; Particle particleArray[MAX_PARTICLES]; // CLUT indexes for 4 bit particle u_short particle12x12[3*12] = { 0x1000, 0x2222, 0x0001, 0x3200, 0x5665, 0x0023, 0x7420, 0x8998, 0x0247, 0xa731, 0xbccb, 0x137a, 0xb852, 0xdeed, 0x258b, 0xc962, 0xeffe, 0x269c, 0xc962, 0xeffe, 0x269c, 0xb852, 0xdeed, 0x258b, 0xa731, 0xbccb, 0x137a, 0x7420, 0x8998, 0x0247, 0x3200, 0x5665, 0x0023, 0x1000, 0x2222, 0x0001 }; // CLUT entries for 4 bit particle u_char particlePalette[16] = { 0, 26, 40, 65, 75, 80, 85, 102, 121, 128, 135, 160, 170, 195, 213, 255 }; // Add a particle to trail left by racer void AddStreamParticle(void) { Particle *part, *target; VECTOR tempVector, partPos; MATRIX tempMatrix; int i; ResetMatrix(tempMatrix.m); RotMatrixX(racer.rot.vx, &tempMatrix); RotMatrixZ(racer.rot.vz, &tempMatrix); RotMatrixY(racer.rot.vy, &tempMatrix); SetVector(&partPos, 0, 4<<8, -(12<<8)); ApplyMatrixLV(&tempMatrix, &partPos, &partPos); partPos.vx += racer.pos.vx; partPos.vy += racer.pos.vy; partPos.vz += racer.pos.vz; target = &particleArray[(partEnd+MAX_PARTICLES-4)%MAX_PARTICLES]; for (i=0; i<4; i++) { part = &particleArray[partEnd%MAX_PARTICLES]; partEnd++; part->pos.vx = partPos.vx+(((target->pos.vx-partPos.vx)*i)>>2); part->pos.vy = partPos.vy+(((target->pos.vy-partPos.vy)*i)>>2); part->pos.vz = partPos.vz+(((target->pos.vz-partPos.vz)*i)>>2); SetVector(&tempVector, (rand()&1023)-512, (rand()&1023)-512, (-(rand()&7)<<7)-(racer.speed>>4)); ApplyMatrixLV(&tempMatrix, &tempVector, &tempVector); part->vel.vx = tempVector.vx; part->vel.vy = tempVector.vy; part->vel.vz = tempVector.vz; part->frame = 8; part->type = rand()&1; // part->pos.vx = partPos.vx + part->vel.vx; // part->pos.vy = partPos.vy + part->vel.vy; // part->pos.vz = partPos.vz + part->vel.vz; } } // Draw particles void DrawParticles(GsOT *ot, int priority){ int i, start, flag; Particle *part; VECTOR newPos; flag = 0; start = partStart; for (i=partStart; iframe>0) { flag = 1; SetRGB(&particleSprite, part->frame<<4, part->frame<<4, part->frame<<4); //if (part->alive == 2) // Draw3dSprite(&part->pos, &part->sprite, ot, (24-part->frame)*400000+200000, 2); //else particleSprite.cx = particleClutX[part->type]; particleSprite.cy = particleClutY[part->type]; SetVector(&newPos, part->pos.vx>>8, part->pos.vy>>8, part->pos.vz>>8); ApplyMatrixLV(&GsWSMATRIX, &newPos, &newPos); newPos.vz += GsWSMATRIX.t[2]; if (newPos.vz > 0) { particleSprite.x = (newPos.vx+GsWSMATRIX.t[0])*projection/newPos.vz; particleSprite.y = (newPos.vy+GsWSMATRIX.t[1])*projection/newPos.vz; particleSprite.scalex = 320000/newPos.vz; particleSprite.scaley = 200000/newPos.vz; GsSortSprite(&particleSprite, ot, newPos.vz >> priority); } part->pos.vx += part->vel.vx; part->pos.vy += part->vel.vy; part->pos.vz += part->vel.vz; part->vel.vy -= 1; if (part->frame > 0) part->frame--; } } partStart=start; if (partStart>MAX_PARTICLES && partEnd>MAX_PARTICLES) { partStart %= MAX_PARTICLES; partEnd %= MAX_PARTICLES; } } // Load particle onto frame buffer void InitParticle(int x, int y) { RECT rect; int u, v; setRECT(&rect, x, y, 3, 12); LoadImage(&rect, (u_long *)particle12x12); DrawSync(0); u = x & 63; v = y & 255; particleSprite.attribute = (1<<30) + (1<<28); particleSprite.mx = particleSprite.my = 6; particleSprite.w = particleSprite.h = 12; particleSprite.tpage = GetTPage(0, 1, x-u, y-v); particleSprite.u = u<<2; // It's a 4 bit image remember particleSprite.v = v; SetRGB(&particleSprite, 128, 128, 128); particleSprite.scalex = ONE*3*1.6; particleSprite.scaley = ONE*3; particleSprite.rotate = 0; partStart = partEnd = 0; for (u=0; u>15, 0, 31); g = LimitRange(g1*particlePalette[i]>>15, 0, 31); b = LimitRange(b1*particlePalette[i]>>15, 0, 31); // Convert to CLUT data palette[i] = (1<<15) + r + (g<<5) + (b<<10); r1 += dr; g1 += dg; b1 += db; } setRECT(&rect, x, y, 16, 1); LoadImage(&rect, (u_long *)palette); DrawSync(0); } void Draw3dSprite(VECTOR *pos, GsSPRITE *sprite, GsOT *ot, long scale, int priority) { VECTOR newPos; SetVector(&newPos, pos->vx>>8, pos->vy>>8, pos->vz>>8); ApplyMatrixLV(&GsWSMATRIX, &newPos, &newPos); // The -16 is a bodge to correct some sorting problems newPos.vz += GsWSMATRIX.t[2]; if (newPos.vz > 0) { sprite->x = (newPos.vx+GsWSMATRIX.t[0])*projection/newPos.vz; sprite->y = (newPos.vy+GsWSMATRIX.t[1])*projection/newPos.vz; sprite->scalex = sprite->scaley = scale/newPos.vz; GsSortSprite(sprite, ot, newPos.vz >> priority); } } void LoadTexture(long TIMdata, GsIMAGE *imageInfo) { RECT rect; GsGetTimInfo((u_long *)(TIMdata+4), imageInfo); rect.x = imageInfo->px; rect.y = imageInfo->py; rect.w = imageInfo->pw; rect.h = imageInfo->ph; LoadImage(&rect, imageInfo->pixel); DrawSync(0); if ((imageInfo->pmode>>3) & 0x01) { rect.x = imageInfo->cx; rect.y = imageInfo->cy; rect.w = imageInfo->cw; rect.h = imageInfo->ch; LoadImage(&rect, imageInfo->clut); DrawSync(0); } }