Merge pull request #32 from Clownacy/master

More NPCs, overhauled graphics system, and fixed audio
This commit is contained in:
Cucky 2019-01-30 16:13:58 -05:00 committed by GitHub
commit fafce1f4c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 1664 additions and 253 deletions

View file

@ -73,6 +73,7 @@ SOURCES = \
NpcAct120 \ NpcAct120 \
NpcAct140 \ NpcAct140 \
NpcAct200 \ NpcAct200 \
NpcAct260 \
NpcAct280 \ NpcAct280 \
NpcAct300 \ NpcAct300 \
NpcAct340 \ NpcAct340 \

View file

@ -64,101 +64,157 @@ bool Flip_SystemTask()
return true; return true;
} }
bool StartDirectDraw() static bool IsEnableBitmap(SDL_RWops *fp)
{ {
//Create renderer char str[16];
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE); const char *extra_text = "(C)Pixel";
return true;
}
void EndDirectDraw() const size_t len = strlen(extra_text);
{
//Release all surfaces fp->seek(fp, -len, RW_SEEK_END);
for (int i = 0; i < SURFACE_ID_MAX; i++) fp->read(fp, str, 1, len);
{ fp->seek(fp, 0, RW_SEEK_SET);
if (surf[i].texture) return memcmp(str, extra_text, len) == 0;
{
SDL_DestroyTexture(surf[i].texture);
surf[i].texture = NULL;
}
}
} }
void ReleaseSurface(int s) void ReleaseSurface(int s)
{ {
//Release the surface we want to release //Release the surface we want to release
if (surf[s].texture) if (surf[s].in_use)
{ {
SDL_DestroyTexture(surf[s].texture); SDL_DestroyTexture(surf[s].texture);
surf[s].texture = NULL; SDL_FreeSurface(surf[s].surface);
surf[s].in_use = false;
} }
} }
bool MakeSurface(SDL_RWops *fp, int surf_no) bool MakeSurface_Generic(int bxsize, int bysize, int surf_no)
{ {
//Check if surf_no can be used bool success = false;
if (surf_no > SURFACE_ID_MAX)
#ifdef FIX_BUGS
if (surf_no >= SURFACE_ID_MAX)
#else
if (surf_no > SURFACE_ID_MAX) // OOPS (should be '>=')
#endif
{ {
printf("Tried to create surface with invalid id %d\n", surf_no); printf("Tried to create drawable surface at invalid slot (%d - maximum is %d)\n", surf_no, SURFACE_ID_MAX);
return false;
} }
if (surf[surf_no].texture) else
{ {
printf("Tried to create surface at id %d, but there's already a texture there\n", surf_no); if (surf[surf_no].in_use == true)
return false; {
printf("Tried to create drawable surface at occupied slot (%d)\n", surf_no);
}
else
{
//Create surface
surf[surf_no].surface = SDL_CreateRGBSurfaceWithFormat(0, bxsize * gWindowScale, bysize * gWindowScale, 0, SDL_PIXELFORMAT_RGBA32);
if (surf[surf_no].surface == NULL)
{
printf("Failed to create drawable surface %d (SDL_CreateRGBSurfaceWithFormat)\nSDL Error: %s\n", surf_no, SDL_GetError());
}
else
{
surf[surf_no].texture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, bxsize * gWindowScale, bysize * gWindowScale);
if (surf[surf_no].texture == NULL)
{
printf("Failed to create drawable surface %d (SDL_CreateTexture)\nSDL Error: %s\n", surf_no, SDL_GetError());
SDL_FreeSurface(surf[surf_no].surface);
}
else
{
surf[surf_no].in_use = true;
success = true;
}
}
}
} }
//Load surface from file return success;
SDL_Surface *surface = SDL_LoadBMP_RW(fp, 1);
if (!surface)
{
printf("Couldn't load bitmap for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError());
return false;
}
//Make sure surface has color key on
SDL_SetColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 0, 0, 0));
//Get texture from surface
SDL_Texture *texture = SDL_CreateTextureFromSurface(gRenderer, surface);
if (!texture)
{
printf("Failed to convert SDL_Surface to SDL_Texture for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError());
return false;
}
//Create real texture, and copy loaded texture here (has texture target access)
int w, h;
SDL_QueryTexture(texture, NULL, NULL, &w, &h);
SDL_Texture *textureAccessible = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, w * gWindowScale, h * gWindowScale);
if (!textureAccessible)
{
printf("Failed to create real texture for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError());
return false;
}
SDL_SetTextureBlendMode(textureAccessible, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(gRenderer, textureAccessible);
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 0);
SDL_RenderClear(gRenderer);
SDL_RenderCopy(gRenderer, texture, NULL, NULL);
SDL_SetRenderTarget(gRenderer, NULL);
//Set surface's metadata
surf[surf_no].texture = textureAccessible;
//Free surface and texture
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);
printf(" ^ Successfully loaded\n");
return true;
} }
bool MakeSurface_File(const char *name, int surf_no) static void FlushSurface(int surf_no)
{
unsigned char *raw_pixels;
int pitch;
SDL_LockTexture(surf[surf_no].texture, NULL, (void**)&raw_pixels, &pitch);
unsigned char (*src_pixels)[surf[surf_no].surface->pitch / 4][4] = (unsigned char (*)[surf[surf_no].surface->pitch/ 4][4])surf[surf_no].surface->pixels;
unsigned char (*dst_pixels)[pitch / 4][4] = (unsigned char (*)[pitch/ 4][4])raw_pixels;
for (unsigned int h = 0; h < surf[surf_no].surface->h; ++h)
{
for (unsigned int w = 0; w < surf[surf_no].surface->w; ++w)
{
dst_pixels[h][w][0] = src_pixels[h][w][0];
dst_pixels[h][w][1] = src_pixels[h][w][1];
dst_pixels[h][w][2] = src_pixels[h][w][2];
if (src_pixels[h][w][0] || src_pixels[h][w][1] || src_pixels[h][w][2]) // Colour-key
dst_pixels[h][w][3] = 0xFF;
else
dst_pixels[h][w][3] = 0;
}
}
SDL_UnlockTexture(surf[surf_no].texture);
}
static bool LoadBitmap(SDL_RWops *fp, int surf_no, bool create_surface)
{
bool success = false;
if (surf_no >= SURFACE_ID_MAX)
{
printf("Tried to load bitmap at invalid slot (%d - maximum is %d\n", surf_no, SURFACE_ID_MAX);
}
else
{
if (create_surface && surf[surf_no].in_use)
{
printf("Tried to create drawable surface at occupied slot (%d)\n", surf_no);
}
else
{
SDL_Surface *surface = SDL_LoadBMP_RW(fp, 1);
if (surface == NULL)
{
printf("Couldn't load bitmap for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError());
}
else
{
if (create_surface == false || MakeSurface_Generic(surface->w, surface->h, surf_no))
{
SDL_Surface *converted_surface = SDL_ConvertSurface(surface, surf[surf_no].surface->format, 0);
if (converted_surface == NULL)
{
printf("Couldn't convert bitmap to surface format (surface id %d)\nSDL Error: %s\n", surf_no, SDL_GetError());
}
else
{
SDL_Rect dst_rect = {0, 0, converted_surface->w * gWindowScale, converted_surface->h * gWindowScale};
SDL_BlitScaled(converted_surface, NULL, surf[surf_no].surface, &dst_rect);
SDL_FreeSurface(converted_surface);
surf[surf_no].needs_updating = true;
printf(" ^ Successfully loaded\n");
success = true;
}
}
SDL_FreeSurface(surface);
}
}
}
return success;
}
static bool LoadBitmap_File(const char *name, int surf_no, bool create_surface)
{ {
char path[PATH_LENGTH]; char path[PATH_LENGTH];
SDL_RWops *fp; SDL_RWops *fp;
@ -168,9 +224,16 @@ bool MakeSurface_File(const char *name, int surf_no)
fp = SDL_RWFromFile(path, "rb"); fp = SDL_RWFromFile(path, "rb");
if (fp) if (fp)
{ {
printf("Loading surface (as .pbm) from %s for surface id %d\n", path, surf_no); if (!IsEnableBitmap(fp))
if (MakeSurface(fp, surf_no)) {
return true; printf("Tried to load bitmap to surface %d, but it's missing the '(C)Pixel' string\n", surf_no);
}
else
{
printf("Loading surface (as .pbm) from %s for surface id %d\n", path, surf_no);
if (LoadBitmap(fp, surf_no, create_surface))
return true;
}
} }
//Attempt to load BMP //Attempt to load BMP
@ -178,23 +241,31 @@ bool MakeSurface_File(const char *name, int surf_no)
fp = SDL_RWFromFile(path, "rb"); fp = SDL_RWFromFile(path, "rb");
if (fp) if (fp)
{ {
printf("Loading surface (as .bmp) from %s for surface id %d\n", path, surf_no); if (!IsEnableBitmap(fp))
if (MakeSurface(fp, surf_no)) {
return true; printf("Tried to load bitmap to surface %d, but it's missing the '(C)Pixel' string\n", surf_no);
}
else
{
printf("Loading surface (as .bmp) from %s for surface id %d\n", path, surf_no);
if (LoadBitmap(fp, surf_no, create_surface))
return true;
}
} }
printf("Failed to open file %s\n", name); printf("Failed to open file %s\n", name);
return false; return false;
} }
bool MakeSurface_Resource(const char *res, int surf_no) static bool LoadBitmap_Resource(const char *res, int surf_no, bool create_surface)
{ {
SDL_RWops *fp = FindResource(res); SDL_RWops *fp = FindResource(res);
if (fp) if (fp)
{ {
printf("Loading surface from resource %s for surface id %d\n", res, surf_no); printf("Loading surface from resource %s for surface id %d\n", res, surf_no);
if (MakeSurface(fp, surf_no)) if (LoadBitmap(fp, surf_no, create_surface))
return true; return true;
} }
@ -202,34 +273,24 @@ bool MakeSurface_Resource(const char *res, int surf_no)
return false; return false;
} }
bool MakeSurface_File(const char *name, int surf_no)
{
return LoadBitmap_File(name, surf_no, true);
}
bool MakeSurface_Resource(const char *res, int surf_no)
{
return LoadBitmap_Resource(res, surf_no, true);
}
bool ReloadBitmap_File(const char *name, int surf_no) bool ReloadBitmap_File(const char *name, int surf_no)
{ {
ReleaseSurface(surf_no); return LoadBitmap_File(name, surf_no, false);
return MakeSurface_File(name, surf_no);
} }
bool ReloadBitmap_Resource(const char *res, int surf_no) bool ReloadBitmap_Resource(const char *res, int surf_no)
{ {
ReleaseSurface(surf_no); return LoadBitmap_Resource(res, surf_no, false);
return MakeSurface_Resource(res, surf_no);
}
bool MakeSurface_Generic(int bxsize, int bysize, int surf_no)
{
//Delete old surface
ReleaseSurface(surf_no);
//Create surface
surf[surf_no].texture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, bxsize * gWindowScale, bysize * gWindowScale);
if (!surf[surf_no].texture)
{
printf("Failed to create drawable surface %d\nSDL Error: %s\n", surf_no, SDL_GetError());
return false;
}
SDL_SetTextureBlendMode(surf[surf_no].texture, SDL_BLENDMODE_BLEND);
return true;
} }
SDL_Rect RectToSDLRect(RECT *rect) SDL_Rect RectToSDLRect(RECT *rect)
@ -246,42 +307,27 @@ void BackupSurface(int surf_no, RECT *rect)
//Get texture of what's currently rendered on screen //Get texture of what's currently rendered on screen
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, SDL_PIXELFORMAT_RGBA32); SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, SDL_PIXELFORMAT_RGBA32);
SDL_RenderReadPixels(gRenderer, nullptr, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch); SDL_RenderReadPixels(gRenderer, NULL, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch);
SDL_Texture *screenTexture = SDL_CreateTextureFromSurface(gRenderer, surface);
//Free surface
SDL_FreeSurface(surface);
//Get rects //Get rects
SDL_Rect frameRect = RectToSDLRect(rect); SDL_Rect frameRect = RectToSDLRect(rect);
frameRect = {frameRect.x * gWindowScale, frameRect.y * gWindowScale, frameRect.w * gWindowScale, frameRect.h * gWindowScale}; frameRect = {frameRect.x * gWindowScale, frameRect.y * gWindowScale, frameRect.w * gWindowScale, frameRect.h * gWindowScale};
SDL_Texture *textureAccessible = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, frameRect.w, frameRect.h); SDL_BlitSurface(surface, &frameRect, surf[surf_no].surface, &frameRect);
surf[surf_no].needs_updating = true;
if (!textureAccessible) //Free surface
{ SDL_FreeSurface(surface);
printf("Failed to create real texture for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError());
return;
}
SDL_SetTextureBlendMode(textureAccessible, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(gRenderer, textureAccessible);
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 0);
SDL_RenderClear(gRenderer);
SDL_RenderCopy(gRenderer, screenTexture, &frameRect, NULL);
SDL_SetRenderTarget(gRenderer, NULL);
//Set surface's metadata
surf[surf_no].texture = textureAccessible;
//Free stuff
SDL_DestroyTexture(screenTexture);
} }
void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transparency static void DrawBitmap(RECT *rcView, int x, int y, RECT *rect, int surf_no, bool transparent)
{ {
if (surf[surf_no].needs_updating)
{
FlushSurface(surf_no);
surf[surf_no].needs_updating = false;
}
//Get SDL_Rects //Get SDL_Rects
SDL_Rect clipRect = RectToSDLRect(rcView); SDL_Rect clipRect = RectToSDLRect(rcView);
@ -295,6 +341,8 @@ void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transpare
clipRect = {clipRect.x * gWindowScale, clipRect.y * gWindowScale, clipRect.w * gWindowScale, clipRect.h * gWindowScale}; clipRect = {clipRect.x * gWindowScale, clipRect.y * gWindowScale, clipRect.w * gWindowScale, clipRect.h * gWindowScale};
SDL_RenderSetClipRect(gRenderer, &clipRect); SDL_RenderSetClipRect(gRenderer, &clipRect);
SDL_SetTextureBlendMode(surf[surf_no].texture, transparent ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE);
//Draw to screen //Draw to screen
if (SDL_RenderCopy(gRenderer, surf[surf_no].texture, &frameRect, &destRect) < 0) if (SDL_RenderCopy(gRenderer, surf[surf_no].texture, &frameRect, &destRect) < 0)
printf("Failed to draw texture %d\nSDL Error: %s\n", surf_no, SDL_GetError()); printf("Failed to draw texture %d\nSDL Error: %s\n", surf_no, SDL_GetError());
@ -303,36 +351,14 @@ void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transpare
SDL_RenderSetClipRect(gRenderer, NULL); SDL_RenderSetClipRect(gRenderer, NULL);
} }
void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transparency
{
DrawBitmap(rcView, x, y, rect, surf_no, true);
}
void PutBitmap4(RECT *rcView, int x, int y, RECT *rect, int surf_no) //No Transparency void PutBitmap4(RECT *rcView, int x, int y, RECT *rect, int surf_no) //No Transparency
{ {
//Get SDL_Rects DrawBitmap(rcView, x, y, rect, surf_no, false);
SDL_Rect clipRect = RectToSDLRect(rcView);
SDL_Rect frameRect = RectToSDLRect(rect);
frameRect = {frameRect.x * gWindowScale, frameRect.y * gWindowScale, frameRect.w * gWindowScale, frameRect.h * gWindowScale};
//Get dest rect
SDL_Rect destRect = {x * gWindowScale, y * gWindowScale, frameRect.w, frameRect.h};
//Set cliprect
clipRect = {clipRect.x * gWindowScale, clipRect.y * gWindowScale, clipRect.w * gWindowScale, clipRect.h * gWindowScale};
SDL_RenderSetClipRect(gRenderer, &clipRect);
//Get original drawing colour
uint8_t origR, origG, origB, origA;
SDL_GetRenderDrawColor(gRenderer, &origR, &origG, &origB, &origA);
//Draw black behind texture
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 0xFF);
SDL_RenderFillRect(gRenderer, &destRect);
//Draw texture
if (SDL_RenderCopy(gRenderer, surf[surf_no].texture, &frameRect, &destRect) < 0)
printf("Failed to draw texture %d\nSDL Error: %s\n", surf_no, SDL_GetError());
//Restore original colour, and undo cliprect
SDL_RenderSetClipRect(gRenderer, NULL);
SDL_SetRenderDrawColor(gRenderer, origR, origG, origB, origA);
} }
void Surface2Surface(int x, int y, RECT *rect, int to, int from) void Surface2Surface(int x, int y, RECT *rect, int to, int from)
@ -342,21 +368,8 @@ void Surface2Surface(int x, int y, RECT *rect, int to, int from)
SDL_Rect frameRect = RectToSDLRect(rect); SDL_Rect frameRect = RectToSDLRect(rect);
frameRect = {frameRect.x * gWindowScale, frameRect.y * gWindowScale, frameRect.w * gWindowScale, frameRect.h * gWindowScale}; frameRect = {frameRect.x * gWindowScale, frameRect.y * gWindowScale, frameRect.w * gWindowScale, frameRect.h * gWindowScale};
//Target surface SDL_BlitSurface(surf[from].surface, &frameRect, surf[to].surface, &rcSet);
if (!surf[to].texture) surf[to].needs_updating = true;
{
printf("Tried to draw to surface %d, which doesn't exist\n", to);
return;
}
SDL_SetRenderTarget(gRenderer, surf[to].texture);
//Draw texture
if (SDL_RenderCopy(gRenderer, surf[from].texture, &frameRect, &rcSet) < 0)
printf("Failed to draw texture %d to %d\nSDL Error: %s\n", from, to, SDL_GetError());
//Stop targetting surface
SDL_SetRenderTarget(gRenderer, NULL);
} }
void CortBox(RECT *rect, uint32_t col) void CortBox(RECT *rect, uint32_t col)
@ -376,26 +389,11 @@ void CortBox2(RECT *rect, uint32_t col, int surf_no)
SDL_Rect destRect = RectToSDLRect(rect); SDL_Rect destRect = RectToSDLRect(rect);
destRect = {destRect.x * gWindowScale, destRect.y * gWindowScale, destRect.w * gWindowScale, destRect.h * gWindowScale}; destRect = {destRect.x * gWindowScale, destRect.y * gWindowScale, destRect.w * gWindowScale, destRect.h * gWindowScale};
//Target surface
if (!surf[surf_no].texture)
{
printf("Tried to draw a rectangle to surface %d, which doesn't exist\n", surf_no);
return;
}
SDL_SetRenderTarget(gRenderer, surf[surf_no].texture);
const unsigned char col_red = (col & 0xFF0000) >> 16; const unsigned char col_red = (col & 0xFF0000) >> 16;
const unsigned char col_green = (col & 0x00FF00) >> 8; const unsigned char col_green = (col & 0x00FF00) >> 8;
const unsigned char col_blue = col & 0x0000FF; const unsigned char col_blue = col & 0x0000FF;
const unsigned char col_alpha = (col_red || col_green || col_blue) ? 0xFF : 0; SDL_FillRect(surf[surf_no].surface, &destRect, SDL_MapRGB(surf[surf_no].surface->format, col_red, col_green, col_blue));
surf[surf_no].needs_updating = true;
//Set colour and draw
SDL_SetRenderDrawColor(gRenderer, col_red, col_green, col_blue, col_alpha);
SDL_RenderFillRect(gRenderer, &destRect);
//Stop targetting surface
SDL_SetRenderTarget(gRenderer, NULL);
} }
#ifdef WINDOWS #ifdef WINDOWS
@ -491,12 +489,24 @@ void InitTextObject(const char *font_name)
void PutText(int x, int y, const char *text, uint32_t color) void PutText(int x, int y, const char *text, uint32_t color)
{ {
DrawText(gFont, gRenderer, NULL, x * gWindowScale, y * gWindowScale, color, text, strlen(text)); int surface_width, surface_height;
SDL_GetRendererOutputSize(gRenderer, &surface_width, &surface_height);
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, surface_width, surface_height, 0, SDL_PIXELFORMAT_RGBA32);
SDL_RenderReadPixels(gRenderer, NULL, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch);
DrawText(gFont, surface, x * gWindowScale, y * gWindowScale, color, text, strlen(text));
SDL_Texture *screen_texture = SDL_CreateTextureFromSurface(gRenderer, surface);
SDL_FreeSurface(surface);
SDL_RenderCopy(gRenderer, screen_texture, NULL, NULL);
SDL_DestroyTexture(screen_texture);
} }
void PutText2(int x, int y, const char *text, uint32_t color, int surf_no) void PutText2(int x, int y, const char *text, uint32_t color, int surf_no)
{ {
DrawText(gFont, gRenderer, surf[surf_no].texture, x * gWindowScale, y * gWindowScale, color, text, strlen(text)); DrawText(gFont, surf[surf_no].surface, x * gWindowScale, y * gWindowScale, color, text, strlen(text));
surf[surf_no].needs_updating = true;
} }
void EndTextObject() void EndTextObject()
@ -505,3 +515,17 @@ void EndTextObject()
UnloadFont(gFont); UnloadFont(gFont);
gFont = nullptr; gFont = nullptr;
} }
bool StartDirectDraw()
{
//Create renderer
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
return true;
}
void EndDirectDraw()
{
//Release all surfaces
for (int i = 0; i < SURFACE_ID_MAX; i++)
ReleaseSurface(i);
}

View file

@ -45,6 +45,9 @@ enum Surface_Ids
struct SURFACE struct SURFACE
{ {
bool in_use;
bool needs_updating;
SDL_Surface *surface;
SDL_Texture *texture; SDL_Texture *texture;
}; };

View file

@ -175,20 +175,12 @@ FontObject* LoadFont(const char *font_filename, unsigned int cell_width, unsigne
return font_object; return font_object;
} }
void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, unsigned long colour, const char *string, size_t string_length) void DrawText(FontObject *font_object, SDL_Surface *surface, int x, int y, unsigned long colour, const char *string, size_t string_length)
{ {
if (font_object != NULL) if (font_object != NULL)
{ {
const unsigned char colours[3] = {(unsigned char)(colour >> 16), (unsigned char)(colour >> 8), (unsigned char)colour}; const unsigned char colours[3] = {(unsigned char)(colour >> 16), (unsigned char)(colour >> 8), (unsigned char)colour};
SDL_Texture *old_render_target = SDL_GetRenderTarget(renderer);
SDL_SetRenderTarget(renderer, texture);
int surface_width, surface_height;
SDL_GetRendererOutputSize(renderer, &surface_width, &surface_height);
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, surface_width, surface_height, 0, SDL_PIXELFORMAT_RGBA32);
SDL_RenderReadPixels(renderer, NULL, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch);
unsigned char (*surface_buffer)[surface->pitch / 4][4] = (unsigned char (*)[surface->pitch / 4][4])surface->pixels; unsigned char (*surface_buffer)[surface->pitch / 4][4] = (unsigned char (*)[surface->pitch / 4][4])surface->pixels;
FT_Face face = font_object->face; FT_Face face = font_object->face;
@ -238,11 +230,11 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text
const int letter_x = x + pen_x + face->glyph->bitmap_left; const int letter_x = x + pen_x + face->glyph->bitmap_left;
const int letter_y = y + ((FT_MulFix(face->ascender, face->size->metrics.y_scale) + (64 - 1)) / 64) - (face->glyph->metrics.horiBearingY / 64); const int letter_y = y + ((FT_MulFix(face->ascender, face->size->metrics.y_scale) + (64 - 1)) / 64) - (face->glyph->metrics.horiBearingY / 64);
for (int iy = MAX(-letter_y, 0); letter_y + iy < MIN(letter_y + converted.rows, surface_height); ++iy) for (int iy = MAX(-letter_y, 0); letter_y + iy < MIN(letter_y + converted.rows, surface->h); ++iy)
{ {
if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD)
{ {
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width / 3, surface_width); ++ix) for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width / 3, surface->w); ++ix)
{ {
const unsigned char (*font_buffer)[converted.pitch / 3][3] = (unsigned char (*)[converted.pitch / 3][3])converted.buffer; const unsigned char (*font_buffer)[converted.pitch / 3][3] = (unsigned char (*)[converted.pitch / 3][3])converted.buffer;
@ -263,7 +255,7 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text
} }
else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
{ {
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface_width); ++ix) for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface->w); ++ix)
{ {
unsigned char (*font_buffer)[converted.pitch] = (unsigned char (*)[converted.pitch])converted.buffer; unsigned char (*font_buffer)[converted.pitch] = (unsigned char (*)[converted.pitch])converted.buffer;
@ -282,7 +274,7 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text
} }
else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
{ {
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface_width); ++ix) for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface->w); ++ix)
{ {
unsigned char (*font_buffer)[converted.pitch] = (unsigned char (*)[converted.pitch])converted.buffer; unsigned char (*font_buffer)[converted.pitch] = (unsigned char (*)[converted.pitch])converted.buffer;
@ -303,12 +295,6 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text
pen_x += face->glyph->advance.x / 64; pen_x += face->glyph->advance.x / 64;
} }
SDL_Texture *screen_texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
SDL_DestroyTexture(screen_texture);
SDL_SetRenderTarget(renderer, old_render_target);
} }
} }

View file

@ -8,5 +8,5 @@ typedef struct FontObject FontObject;
FontObject* LoadFontFromData(const unsigned char *data, size_t data_size, unsigned int cell_width, unsigned int cell_height); FontObject* LoadFontFromData(const unsigned char *data, size_t data_size, unsigned int cell_width, unsigned int cell_height);
FontObject* LoadFont(const char *font_filename, unsigned int cell_width, unsigned int cell_height); FontObject* LoadFont(const char *font_filename, unsigned int cell_width, unsigned int cell_height);
void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, unsigned long colour, const char *string, size_t string_length); void DrawText(FontObject *font_object, SDL_Surface *surface, int x, int y, unsigned long colour, const char *string, size_t string_length);
void UnloadFont(FontObject *font_object); void UnloadFont(FontObject *font_object);

View file

@ -21,9 +21,10 @@ void ActNpc020(NPCHAR *npc);
void ActNpc021(NPCHAR *npc); void ActNpc021(NPCHAR *npc);
void ActNpc022(NPCHAR *npc); void ActNpc022(NPCHAR *npc);
void ActNpc023(NPCHAR *npc); void ActNpc023(NPCHAR *npc);
void ActNpc024(NPCHAR *npc);
void ActNpc025(NPCHAR *npc); void ActNpc025(NPCHAR *npc);
void ActNpc028(NPCHAR *npc);
void ActNpc029(NPCHAR *npc); void ActNpc029(NPCHAR *npc);
void ActNpc030(NPCHAR *npc); void ActNpc030(NPCHAR *npc);
@ -32,7 +33,7 @@ void ActNpc032(NPCHAR *npc);
void ActNpc034(NPCHAR *npc); void ActNpc034(NPCHAR *npc);
void ActNpc037(NPCHAR *npc); void ActNpc037(NPCHAR *npc);
void ActNpc038(NPCHAR *npc);
void ActNpc039(NPCHAR *npc); void ActNpc039(NPCHAR *npc);
void ActNpc042(NPCHAR *npc); void ActNpc042(NPCHAR *npc);
@ -42,12 +43,14 @@ void ActNpc046(NPCHAR *npc);
void ActNpc058(NPCHAR *npc); void ActNpc058(NPCHAR *npc);
void ActNpc059(NPCHAR *npc); void ActNpc059(NPCHAR *npc);
void ActNpc060(NPCHAR *npc);
void ActNpc061(NPCHAR *npc);
void ActNpc062(NPCHAR *npc); void ActNpc062(NPCHAR *npc);
void ActNpc064(NPCHAR *npc); void ActNpc064(NPCHAR *npc);
void ActNpc065(NPCHAR *npc); void ActNpc065(NPCHAR *npc);
void ActNpc069(NPCHAR *npc);
void ActNpc070(NPCHAR *npc); void ActNpc070(NPCHAR *npc);
void ActNpc071(NPCHAR *npc); void ActNpc071(NPCHAR *npc);
void ActNpc072(NPCHAR *npc); void ActNpc072(NPCHAR *npc);
@ -58,6 +61,8 @@ void ActNpc076(NPCHAR *npc);
void ActNpc077(NPCHAR *npc); void ActNpc077(NPCHAR *npc);
void ActNpc078(NPCHAR *npc); void ActNpc078(NPCHAR *npc);
void ActNpc079(NPCHAR *npc); void ActNpc079(NPCHAR *npc);
void ActNpc080(NPCHAR *npc);
void ActNpc081(NPCHAR *npc);
void ActNpc083(NPCHAR *npc); void ActNpc083(NPCHAR *npc);
void ActNpc084(NPCHAR *npc); void ActNpc084(NPCHAR *npc);
@ -71,10 +76,14 @@ void ActNpc119(NPCHAR *npc);
void ActNpc125(NPCHAR *npc); void ActNpc125(NPCHAR *npc);
void ActNpc145(NPCHAR *npc);
void ActNpc151(NPCHAR *npc); void ActNpc151(NPCHAR *npc);
void ActNpc211(NPCHAR *npc); void ActNpc211(NPCHAR *npc);
void ActNpc278(NPCHAR *npc);
void ActNpc298(NPCHAR *npc); void ActNpc298(NPCHAR *npc);
void ActNpc299(NPCHAR *npc); void ActNpc299(NPCHAR *npc);
void ActNpc300(NPCHAR *npc); void ActNpc300(NPCHAR *npc);

View file

@ -9,6 +9,7 @@
#include "Back.h" #include "Back.h"
#include "Triangle.h" #include "Triangle.h"
#include "Caret.h" #include "Caret.h"
#include "Frame.h"
//Computer //Computer
void ActNpc020(NPCHAR *npc) void ActNpc020(NPCHAR *npc)
@ -108,6 +109,184 @@ void ActNpc023(NPCHAR *npc)
npc->rect = rect[npc->ani_no]; npc->rect = rect[npc->ani_no];
} }
//Power Critter
void ActNpc024(NPCHAR *npc)
{
RECT rcLeft[6];
RECT rcRight[6];
rcLeft[0] = {0, 0, 24, 24};
rcLeft[1] = {24, 0, 48, 24};
rcLeft[2] = {48, 0, 72, 24};
rcLeft[3] = {72, 0, 96, 24};
rcLeft[4] = {96, 0, 120, 24};
rcLeft[5] = {120, 0, 144, 24};
rcRight[0] = {0, 24, 24, 48};
rcRight[1] = {24, 24, 48, 48};
rcRight[2] = {48, 24, 72, 48};
rcRight[3] = {72, 24, 96, 48};
rcRight[4] = {96, 24, 120, 48};
rcRight[5] = {120, 24, 144, 48};
switch (npc->act_no)
{
case 0:
npc->y += 0x600;
npc->act_no = 1;
// Fallthrough
case 1:
if (npc->act_wait >= 8 && gMC.x > npc->x - 0x10000 && gMC.x < npc->x + 0x10000 && gMC.y > npc->y - 0x10000 && gMC.y < npc->y + 0x6000)
{
if (gMC.x < npc->x)
npc->direct = 0;
else
npc->direct = 2;
npc->ani_no = 1;
}
else
{
if (npc->act_wait < 8)
++npc->act_wait;
npc->ani_no = 0;
}
if (npc->shock)
{
npc->act_no = 2;
npc->ani_no = 0;
npc->act_wait = 0;
}
if (npc->act_wait >= 8 && gMC.x > npc->x - 0xC000 && gMC.x < npc->x + 0xC000 && gMC.y > npc->y - 0xC000 && gMC.y < npc->y + 0x6000)
{
npc->act_no = 2;
npc->ani_no = 0;
npc->act_wait = 0;
}
break;
case 2:
if (++npc->act_wait > 8)
{
npc->act_no = 3;
npc->ani_no = 2;
npc->ym = -0x5FF;
PlaySoundObject(108, 1);
if (gMC.x < npc->x)
npc->direct = 0;
else
npc->direct = 2;
if (npc->direct == 0)
npc->xm = -0x100;
else
npc->xm = 0x100;
}
break;
case 3:
if (npc->ym > 0x200)
{
npc->tgt_y = npc->y;
npc->act_no = 4;
npc->ani_no = 3;
npc->act_wait = 0;
npc->act_wait = 0; // lol duplicate line
}
break;
case 4:
if (gMC.x > npc->x)
npc->direct = 2;
else
npc->direct = 0;
++npc->act_wait;
if (npc->flag & 7 || npc->act_wait > 100)
{
npc->damage = 12;
npc->act_no = 5;
npc->ani_no = 2;
npc->xm /= 2;
}
else
{
if (npc->act_wait % 4 == 1)
PlaySoundObject(110, 1);
if (++npc->ani_wait > 0)
{
npc->ani_wait = 0;
++npc->ani_no;
}
if (npc->ani_no > 5)
npc->ani_no = 3;
}
break;
case 5:
if (npc->flag & 8)
{
npc->damage = 2;
npc->xm = 0;
npc->act_wait = 0;
npc->ani_no = 0;
npc->act_no = 1;
PlaySoundObject(26, 1);
SetQuake(30);
}
break;
}
if (npc->act_no == 4)
{
if (gMC.x > npc->x)
npc->xm += 0x20;
else
npc->xm -= 0x20;
if (npc->tgt_y < npc->y)
npc->ym -= 0x10;
else
npc->ym += 0x10;
if (npc->ym > 0x200)
npc->ym = 0x200;
if (npc->ym < -0x200)
npc->ym = -0x200;
if (npc->xm > 0x200)
npc->xm = 0x200;
if (npc->xm < -0x200)
npc->xm = -0x200;
}
else
{
npc->ym += 0x20;
if (npc->ym > 0x5FF)
npc->ym = 0x5FF;
}
npc->x += npc->xm;
npc->y += npc->ym;
if (npc->direct == 0)
npc->rect = rcLeft[npc->ani_no];
else
npc->rect = rcRight[npc->ani_no];
}
// Egg Corridor lift // Egg Corridor lift
void ActNpc025(NPCHAR *npc) void ActNpc025(NPCHAR *npc)
{ {
@ -234,6 +413,186 @@ void ActNpc025(NPCHAR *npc)
npc->rect = rcLeft[npc->ani_no]; npc->rect = rcLeft[npc->ani_no];
} }
//Flying Critter (Grasstown)
void ActNpc028(NPCHAR *npc)
{
RECT rcLeft[6];
RECT rcRight[6];
rcLeft[0] = {0, 48, 16, 64};
rcLeft[1] = {16, 48, 32, 64};
rcLeft[2] = {32, 48, 48, 64};
rcLeft[3] = {48, 48, 64, 64};
rcLeft[4] = {64, 48, 80, 64};
rcLeft[5] = {80, 48, 96, 64};
rcRight[0] = {0, 64, 16, 80};
rcRight[1] = {16, 64, 32, 80};
rcRight[2] = {32, 64, 48, 80};
rcRight[3] = {48, 64, 64, 80};
rcRight[4] = {64, 64, 80, 80};
rcRight[5] = {80, 64, 96, 80};
switch (npc->act_no)
{
case 0:
npc->y += 0x600;
npc->act_no = 1;
// Fallthrough
case 1:
if (npc->act_wait >= 8 && gMC.x > npc->x - 0x10000 && gMC.x < npc->x + 0x10000 && gMC.y > npc->y - 0x10000 && gMC.y < npc->y + 0x6000)
{
if (gMC.x < npc->x)
npc->direct = 0;
else
npc->direct = 2;
npc->ani_no = 1;
}
else
{
if (npc->act_wait < 8)
++npc->act_wait;
npc->ani_no = 0;
}
if (npc->shock)
{
npc->act_no = 2;
npc->ani_no = 0;
npc->act_wait = 0;
}
if ( npc->act_wait >= 8 && gMC.x > npc->x - 0xC000 && gMC.x < npc->x + 0xC000 && gMC.y > npc->y - 0xC000 && gMC.y < npc->y + 0x6000)
{
npc->act_no = 2;
npc->ani_no = 0;
npc->act_wait = 0;
}
break;
case 2:
if (++npc->act_wait > 8)
{
npc->act_no = 3;
npc->ani_no = 2;
npc->ym = -1228;
PlaySoundObject(30, 1);
if (gMC.x < npc->x)
npc->direct = 0;
else
npc->direct = 2;
if (npc->direct == 0)
npc->xm = -0x100;
else
npc->xm = 0x100;
}
break;
case 3:
if (npc->ym > 0x100)
{
npc->tgt_y = npc->y;
npc->act_no = 4;
npc->ani_no = 3;
npc->act_wait = 0;
npc->act_wait = 0; // lol duplicate line
}
break;
case 4:
if (gMC.x > npc->x)
npc->direct = 2;
else
npc->direct = 0;
++npc->act_wait;
if (npc->flag & 7 || npc->act_wait > 100)
{
npc->damage = 3;
npc->act_no = 5;
npc->ani_no = 2;
npc->xm /= 2;
}
else
{
if (npc->act_wait % 4 == 1)
PlaySoundObject(109, 1);
if (npc->flag & 8)
npc->ym = -0x200;
if (++npc->ani_wait > 0)
{
npc->ani_wait = 0;
++npc->ani_no;
}
if (npc->ani_no > 5)
npc->ani_no = 3;
}
break;
case 5:
if (npc->flag & 8)
{
npc->damage = 2;
npc->xm = 0;
npc->act_wait = 0;
npc->ani_no = 0;
npc->act_no = 1;
PlaySoundObject(23, 1);
}
break;
}
if (npc->act_no == 4)
{
if (gMC.x > npc->x)
npc->xm += 0x20;
else
npc->xm -= 0x20;
if (npc->tgt_y < npc->y)
npc->ym -= 0x10;
else
npc->ym += 0x10;
if (npc->ym > 0x200)
npc->ym = 0x200;
if (npc->ym < -0x200)
npc->ym = -0x200;
if (npc->xm > 0x200)
npc->xm = 0x200;
if (npc->xm < -0x200)
npc->xm = -0x200;
}
else
{
npc->ym += 0x40;
if (npc->ym > 0x5FF)
npc->ym = 0x5FF;
}
npc->x += npc->xm;
npc->y += npc->ym;
if (npc->direct == 0)
npc->rect = rcLeft[npc->ani_no];
else
npc->rect = rcRight[npc->ani_no];
}
//Cthulhu //Cthulhu
void ActNpc029(NPCHAR *npc) void ActNpc029(NPCHAR *npc)
{ {
@ -383,6 +742,42 @@ void ActNpc037(NPCHAR *npc)
npc->rect = rect[npc->ani_no]; npc->rect = rect[npc->ani_no];
} }
//Fireplace
void ActNpc038(NPCHAR *npc)
{
RECT rect[4];
rect[0] = {128, 64, 144, 80};
rect[1] = {144, 64, 160, 80};
rect[2] = {160, 64, 176, 80};
rect[3] = {176, 64, 192, 80};
switch (npc->act_no)
{
case 0:
if (++npc->ani_wait > 3)
{
npc->ani_wait = 0;
++npc->ani_no;
}
if (npc->ani_no > 3)
npc->ani_no = 0;
npc->rect = rect[npc->ani_no];
break;
case 10:
npc->act_no = 11;
SetDestroyNpChar(npc->x, npc->y, npc->view.back, 8);
// Fallthrough
case 11:
npc->rect.left = 0;
npc->rect.right = 0;
break;
}
}
//Save sign //Save sign
void ActNpc039(NPCHAR *npc) void ActNpc039(NPCHAR *npc)
{ {

View file

@ -11,6 +11,408 @@
#include "Map.h" #include "Map.h"
#include "CommonDefines.h" #include "CommonDefines.h"
//Toroko
void ActNpc060(NPCHAR *npc)
{
RECT rcLeft[8];
RECT rcRight[8];
rcLeft[0] = {0, 64, 16, 80};
rcLeft[1] = {16, 64, 32, 80};
rcLeft[2] = {32, 64, 48, 80};
rcLeft[3] = {16, 64, 32, 80};
rcLeft[4] = {48, 64, 64, 80};
rcLeft[5] = {16, 64, 32, 80};
rcLeft[6] = {112, 64, 128, 80};
rcLeft[7] = {128, 64, 144, 80};
rcRight[0] = {0, 80, 16, 96};
rcRight[1] = {16, 80, 32, 96};
rcRight[2] = {32, 80, 48, 96};
rcRight[3] = {16, 80, 32, 96};
rcRight[4] = {48, 80, 64, 96};
rcRight[5] = {16, 80, 32, 96};
rcRight[6] = {112, 80, 128, 96};
rcRight[7] = {128, 80, 144, 96};
switch ( npc->act_no )
{
case 0:
npc->act_no = 1;
npc->ani_no = 0;
npc->ani_wait = 0;
npc->xm = 0;
// Fallthrough
case 1:
if (Random(0, 120) == 10)
{
npc->act_no = 2;
npc->act_wait = 0;
npc->ani_no = 1;
}
if (npc->x - 0x2000 < gMC.x && npc->x + 0x2000 > gMC.x && npc->y - 0x2000 < gMC.y && npc->y + 0x2000 > gMC.y)
{
if (npc->x <= gMC.x)
npc->direct = 2;
else
npc->direct = 0;
}
break;
case 2:
if (++npc->act_wait > 8)
{
npc->act_no = 1;
npc->ani_no = 0;
}
break;
case 3:
npc->act_no = 4;
npc->ani_no = 1;
npc->ani_wait = 0;
// Fallthrough
case 4:
if (++npc->ani_wait > 2)
{
npc->ani_wait = 0;
++npc->ani_no;
}
if (npc->ani_no > 4)
npc->ani_no = 1;
if (npc->flag & 1)
{
npc->direct = 2;
npc->xm = 0x200;
}
if (npc->flag & 4)
{
npc->direct = 0;
npc->xm = -0x200;
}
if (npc->direct)
npc->xm = 0x400;
else
npc->xm = -0x400;
break;
case 6:
npc->act_no = 7;
npc->act_wait = 0;
npc->ani_no = 1;
npc->ani_wait = 0;
npc->ym = -0x400;
// Fallthrough
case 7:
if (++npc->ani_wait > 2)
{
npc->ani_wait = 0;
++npc->ani_no;
}
if (npc->ani_no > 4)
npc->ani_no = 1;
if (npc->direct)
npc->xm = 0x100;
else
npc->xm = -0x100;
if (npc->act_wait++ && npc->flag & 8)
npc->act_no = 3;
break;
case 8:
npc->ani_no = 1;
npc->act_wait = 0;
npc->act_no = 9;
npc->ym = -0x200;
// Fallthrough
case 9:
if (npc->act_wait++ && npc->flag & 8)
npc->act_no = 0;
break;
case 10:
npc->act_no = 11;
npc->ani_no = 6;
npc->ym = -0x400;
PlaySoundObject(50, 1);
if (npc->direct)
npc->xm = 0x100;
else
npc->xm = -0x100;
break;
case 11:
if ( npc->act_wait++ && npc->flag & 8 )
{
npc->act_no = 12;
npc->ani_no = 7;
npc->bits |= 0x2000;
}
break;
case 12:
npc->xm = 0;
break;
}
npc->ym += 0x40;
if (npc->xm > 0x400)
npc->xm = 0x400;
if (npc->xm < -0x400)
npc->xm = -0x400;
if (npc->ym > 0x5FF)
npc->ym = 0x5FF;
npc->x += npc->xm;
npc->y += npc->ym;
if (npc->direct == 0)
npc->rect = rcLeft[npc->ani_no];
else
npc->rect = rcRight[npc->ani_no];
}
//King
void ActNpc061(NPCHAR *npc)
{
RECT rcLeft[11];
RECT rcRight[11];
rcLeft[0] = {224, 32, 240, 48};
rcLeft[1] = {240, 32, 256, 48};
rcLeft[2] = {256, 32, 272, 48};
rcLeft[3] = {272, 32, 288, 48};
rcLeft[4] = {288, 32, 304, 48};
rcLeft[5] = {224, 32, 240, 48};
rcLeft[6] = {304, 32, 320, 48};
rcLeft[7] = {224, 32, 240, 48};
rcLeft[8] = {272, 32, 288, 48};
rcLeft[9] = {0, 0, 0, 0};
rcLeft[10] = {112, 32, 128, 48};
rcRight[0] = {224, 48, 240, 64};
rcRight[1] = {240, 48, 256, 64};
rcRight[2] = {256, 48, 272, 64};
rcRight[3] = {272, 48, 288, 64};
rcRight[4] = {288, 48, 304, 64};
rcRight[5] = {224, 48, 240, 64};
rcRight[6] = {304, 48, 320, 64};
rcRight[7] = {224, 48, 240, 64};
rcRight[8] = {272, 48, 288, 64};
rcRight[9] = {0, 0, 0, 0};
rcRight[10] = {112, 32, 128, 48};
switch (npc->act_no)
{
case 0:
npc->act_no = 1;
npc->ani_no = 0;
npc->ani_wait = 0;
npc->xm = 0;
// Fallthrough
case 1:
if (Random(0, 120) == 10)
{
npc->act_no = 2;
npc->act_wait = 0;
npc->ani_no = 1;
}
break;
case 2:
if (++npc->act_wait > 8)
{
npc->act_no = 1;
npc->ani_no = 0;
}
break;
case 5:
npc->ani_no = 3;
npc->xm = 0;
break;
case 6:
npc->act_no = 7;
npc->act_wait = 0;
npc->ani_wait = 0;
npc->ym = -0x400;
// Fallthrough
case 7:
npc->ani_no = 2;
if (npc->direct)
npc->xm = 0x200;
else
npc->xm = -0x200;
if (npc->act_wait++ && npc->flag & 8)
npc->act_no = 5;
break;
case 8:
npc->act_no = 9;
npc->ani_no = 4;
npc->ani_wait = 0;
// Fallthrough
case 9:
if (++npc->ani_wait > 4)
{
npc->ani_wait = 0;
++npc->ani_no;
}
if (npc->ani_no > 7)
npc->ani_no = 4;
if (npc->direct)
npc->xm = 0x200;
else
npc->xm = -0x200;
break;
case 10:
npc->act_no = 11;
npc->ani_no = 4;
npc->ani_wait = 0;
// Fallthrough
case 11:
if (++npc->ani_wait > 2)
{
npc->ani_wait = 0;
++npc->ani_no;
}
if (npc->ani_no > 7)
npc->ani_no = 4;
if (npc->direct)
npc->xm = 0x400;
else
npc->xm = -0x400;
break;
case 20:
SetNpChar(145, 0, 0, 0, 0, 2, npc, 0x100);
npc->ani_no = 0;
npc->act_no = 0;
break;
case 30:
npc->act_no = 31;
npc->act_wait = 0;
npc->ani_wait = 0;
npc->ym = 0;
// Fallthrough
case 31:
npc->ani_no = 2;
if (npc->direct)
npc->xm = 0x600;
else
npc->xm = -0x600;
if (npc->flag & 1)
{
npc->direct = 2;
npc->act_no = 7;
npc->act_wait = 0;
npc->ani_wait = 0;
npc->ym = -0x400;
npc->xm = 0x200;
PlaySoundObject(71, 1);
SetDestroyNpChar(npc->x, npc->y, 0x800, 4);
}
break;
case 40:
npc->act_no = 42;
npc->act_wait = 0;
npc->ani_no = 8;
PlaySoundObject(29, 1);
// Fallthrough
case 42:
if (++npc->ani_no > 9)
npc->ani_no = 8;
if (++npc->act_wait > 100)
{
for (int i = 0; i < 4; ++i)
SetNpChar(4, npc->x + (Random(-12, 12) * 0x200), npc->y + (Random(-12, 12) * 0x200), Random(-341, 341), Random(-0x600, 0), 0, 0, 0x100);
npc->act_no = 50;
npc->surf = 20;
npc->ani_no = 10;
}
break;
case 60:
npc->ani_no = 6;
npc->act_no = 61;
npc->ym = -0x5FF;
npc->xm = 0x400;
npc->count2 = 1;
break;
case 61:
npc->ym += 0x40;
if (npc->flag & 8)
{
npc->act_no = 0;
npc->count2 = 0;
npc->xm = 0;
}
break;
}
if (npc->act_no < 30 || npc->act_no >= 40)
{
npc->ym += 0x40;
if (npc->xm > 0x400)
npc->xm = 0x400;
if (npc->xm < -0x400)
npc->xm = -0x400;
if (npc->ym > 0x5FF)
npc->ym = 0x5FF;
}
npc->x += npc->xm;
npc->y += npc->ym;
if (npc->direct == 0)
npc->rect = rcLeft[npc->ani_no];
else
npc->rect = rcRight[npc->ani_no];
}
//Kazuma at computer //Kazuma at computer
void ActNpc062(NPCHAR *npc) void ActNpc062(NPCHAR *npc)
{ {
@ -258,6 +660,142 @@ void ActNpc065(NPCHAR *npc)
npc->rect = rect_right[npc->ani_no]; npc->rect = rect_right[npc->ani_no];
} }
//Sparkle
void ActNpc069(NPCHAR *npc)
{
RECT rcLeft[6];
RECT rcRight[6];
rcLeft[0] = {48, 0, 64, 16};
rcLeft[1] = {64, 0, 80, 16};
rcLeft[2] = {80, 0, 96, 16};
rcLeft[3] = {96, 0, 112, 16};
rcLeft[4] = {48, 0, 64, 16};
rcLeft[5] = {112, 0, 128, 16};
rcRight[0] = {48, 16, 64, 32};
rcRight[1] = {64, 16, 80, 32};
rcRight[2] = {80, 16, 96, 32};
rcRight[3] = {96, 16, 112, 32};
rcRight[4] = {48, 16, 64, 32};
rcRight[5] = {112, 16, 128, 32};
switch (npc->act_no)
{
case 0:
npc->act_no = 1;
npc->ani_no = 0;
npc->ani_wait = 0;
npc->xm = 0;
// Fallthrough
case 1:
if (Random(0, 100) == 1)
{
npc->act_no = 2;
npc->act_wait = 0;
npc->ani_no = 1;
}
else
{
if (Random(0, 150) == 1)
{
if (npc->direct == 0)
npc->direct = 2;
else
npc->direct = 0;
}
if (Random(0, 150) == 1)
{
npc->act_no = 3;
npc->act_wait = 50;
npc->ani_no = 0;
}
}
break;
case 2:
if (++npc->act_wait > 8)
{
npc->act_no = 1;
npc->ani_no = 0;
}
break;
case 3:
npc->act_no = 4;
npc->ani_no = 2;
npc->ani_wait = 0;
// Fallthrough
case 4:
if (--npc->act_wait == 0)
npc->act_no = 0;
if (++npc->ani_wait > 2)
{
npc->ani_wait = 0;
++npc->ani_no;
}
if (npc->ani_no > 4)
npc->ani_no = 2;
if (npc->flag & 1)
{
npc->direct = 2;
npc->xm = 0x200;
}
if (npc->flag & 4)
{
npc->direct = 0;
npc->xm = -0x200;
}
if (npc->direct == 0)
npc->xm = -0x100u;
else
npc->xm = 0x100;
break;
case 5:
if (npc->flag & 8)
npc->act_no = 0;
break;
}
switch (npc->act_no)
{
case 1:
case 2:
case 4:
if (npc->shock)
{
npc->ym = -0x200;
npc->ani_no = 5;
npc->act_no = 5;
}
break;
}
npc->ym += 0x40;
if (npc->ym > 0x5FF)
npc->ym = 0x5FF;
npc->x += npc->xm;
npc->y += npc->ym;
if (npc->direct == 0)
npc->rect = rcLeft[npc->ani_no];
else
npc->rect = rcRight[npc->ani_no];
}
//Sparkle //Sparkle
void ActNpc070(NPCHAR *npc) void ActNpc070(NPCHAR *npc)
{ {

View file

@ -10,6 +10,298 @@
#include "Triangle.h" #include "Triangle.h"
#include "Caret.h" #include "Caret.h"
//Gravekeeper
void ActNpc080(NPCHAR *npc)
{
RECT rcLeft[7];
RECT rcRight[7];
rcLeft[0] = {0, 64, 24, 88};
rcLeft[1] = {24, 64, 48, 88};
rcLeft[2] = {0, 64, 24, 88};
rcLeft[3] = {48, 64, 72, 88};
rcLeft[4] = {72, 64, 96, 88};
rcLeft[5] = {96, 64, 120, 88};
rcLeft[6] = {120, 64, 144, 88};
rcRight[0] = {0, 88, 24, 112};
rcRight[1] = {24, 88, 48, 112};
rcRight[2] = {0, 88, 24, 112};
rcRight[3] = {48, 88, 72, 112};
rcRight[4] = {72, 88, 96, 112};
rcRight[5] = {96, 88, 120, 112};
rcRight[6] = {120, 88, 144, 112};
switch (npc->act_no)
{
case 0:
npc->bits &= ~0x20;
npc->act_no = 1;
npc->damage = 0;
npc->hit.front = 0x800;
// Fallthrough
case 1:
npc->ani_no = 0;
if (npc->x - 0x10000 < gMC.x && npc->x + 0x10000 > gMC.x && npc->y - 0x6000 < gMC.y && npc->y + 0x4000 > gMC.y)
{
npc->ani_wait = 0;
npc->act_no = 2;
}
if (npc->shock)
{
npc->ani_no = 1;
npc->ani_wait = 0;
npc->act_no = 2;
npc->bits &= ~0x20u;
}
if (gMC.x >= npc->x)
npc->direct = 2;
else
npc->direct = 0;
break;
case 2:
if (++npc->ani_wait > 6)
{
npc->ani_wait = 0;
++npc->ani_no;
}
if (npc->ani_no > 3)
npc->ani_no = 0;
if (npc->x - 0x2000 < gMC.x && npc->x + 0x2000 > gMC.x)
{
npc->hit.front = 0x2400;
npc->act_wait = 0;
npc->act_no = 3;
npc->bits |= 0x20;
PlaySoundObject(34, 1);
if (npc->direct == 0)
npc->xm = -0x400;
else
npc->xm = 0x400;
}
if (gMC.x >= npc->x)
{
npc->direct = 2;
npc->xm = 0x100;
}
else
{
npc->direct = 0;
npc->xm = -0x100;
}
break;
case 3:
npc->xm = 0;
if (++npc->act_wait > 40)
{
npc->act_wait = 0;
npc->act_no = 4;
PlaySoundObject(106, 1);
}
npc->ani_no = 4;
break;
case 4:
npc->damage = 10;
if (++npc->act_wait > 2)
{
npc->act_wait = 0;
npc->act_no = 5;
}
npc->ani_no = 5;
break;
case 5:
npc->ani_no = 6;
if (++npc->act_wait > 60)
npc->act_no = 0;
break;
}
if (npc->xm < 0 && npc->flag & 1)
npc->xm = 0;
if (npc->xm > 0 && npc->flag & 4)
npc->xm = 0;
npc->ym += 0x20;
if (npc->xm > 0x400)
npc->xm = 0x400;
if (npc->xm < -0x400)
npc->xm = -0x400;
if (npc->ym > 0x5FF)
npc->xm = 0x5FF;
if (npc->ym < -0x5FF)
npc->xm = -0x5FF;
npc->x += npc->xm;
npc->y += npc->ym;
if (npc->direct == 0)
npc->rect = rcLeft[npc->ani_no];
else
npc->rect = rcRight[npc->ani_no];
}
//Giant pignon
void ActNpc081(NPCHAR *npc)
{
RECT rcLeft[6];
RECT rcRight[6];
rcLeft[0] = {144, 64, 168, 88};
rcLeft[1] = {168, 64, 192, 88};
rcLeft[2] = {192, 64, 216, 88};
rcLeft[3] = {216, 64, 240, 88};
rcLeft[4] = {144, 64, 168, 88};
rcLeft[5] = {240, 64, 264, 88};
rcRight[0] = {144, 88, 168, 112};
rcRight[1] = {168, 88, 192, 112};
rcRight[2] = {192, 88, 216, 112};
rcRight[3] = {216, 88, 240, 112};
rcRight[4] = {144, 88, 168, 112};
rcRight[5] = {240, 88, 264, 112};
switch (npc->act_no)
{
case 0:
npc->act_no = 1;
npc->ani_no = 0;
npc->ani_wait = 0;
npc->xm = 0;
// Fallthrough
case 1:
if (Random(0, 100) == 1)
{
npc->act_no = 2;
npc->act_wait = 0;
npc->ani_no = 1;
}
else
{
if (Random(0, 150) == 1)
{
if (npc->direct == 0)
npc->direct = 2;
else
npc->direct = 0;
}
if (Random(0, 150) == 1)
{
npc->act_no = 3;
npc->act_wait = 50;
npc->ani_no = 0;
}
}
break;
case 2:
if (++npc->act_wait > 8)
{
npc->act_no = 1;
npc->ani_no = 0;
}
break;
case 3:
npc->act_no = 4;
npc->ani_no = 2;
npc->ani_wait = 0;
// Fallthrough
case 4:
if (--npc->act_wait == 0)
npc->act_no = 0;
if (++npc->ani_wait > 2)
{
npc->ani_wait = 0;
++npc->ani_no;
}
if (npc->ani_no > 4)
npc->ani_no = 2;
if (npc->flag & 1)
{
npc->direct = 2;
npc->xm = 0x200;
}
if (npc->flag & 4)
{
npc->direct = 0;
npc->xm = -0x200;
}
if (npc->direct == 0)
npc->xm = -0x100;
else
npc->xm = 0x100;
break;
case 5:
if (npc->flag & 8)
npc->act_no = 0;
break;
}
switch (npc->act_no)
{
case 1:
case 2:
case 4:
if (npc->shock )
{
npc->ym = -0x200;
npc->ani_no = 5;
npc->act_no = 5;
if (npc->x >= gMC.x)
npc->xm = -0x100;
else
npc->xm = 0x100;
}
break;
}
npc->ym += 0x40;
if (npc->ym > 0x5FF)
npc->ym = 0x5FF;
npc->x += npc->xm;
npc->y += npc->ym;
if (npc->direct == 0)
npc->rect = rcLeft[npc->ani_no];
else
npc->rect = rcRight[npc->ani_no];
}
//Igor (cutscene) //Igor (cutscene)
void ActNpc083(NPCHAR *npc) void ActNpc083(NPCHAR *npc)
{ {

View file

@ -9,6 +9,46 @@
#include "Back.h" #include "Back.h"
#include "Triangle.h" #include "Triangle.h"
//King's sword
void ActNpc145(NPCHAR *npc)
{
RECT rcLeft[1];
RECT rcRight[1];
rcLeft[0] = {96, 32, 112, 48};
rcRight[0] = {112, 32, 128, 48};
if (npc->act_no == 0)
{
if (npc->pNpc->count2 == 0)
{
if (npc->pNpc->direct == 0)
npc->direct = 0;
else
npc->direct = 2;
}
else
{
if (npc->pNpc->direct == 0)
npc->direct = 2;
else
npc->direct = 0;
}
if (npc->direct == 0)
npc->x = npc->pNpc->x - 0x1400;
else
npc->x = npc->pNpc->x + 0x1400;
npc->y = npc->pNpc->y;
}
if (npc->direct == 0)
npc->rect = rcLeft[npc->ani_no];
else
npc->rect = rcRight[npc->ani_no];
}
//Blue robot (standing) //Blue robot (standing)
void ActNpc151(NPCHAR *npc) void ActNpc151(NPCHAR *npc)
{ {

122
src/NpcAct260.cpp Normal file
View file

@ -0,0 +1,122 @@
#include "WindowsWrapper.h"
#include "NpcAct.h"
#include "MyChar.h"
#include "NpChar.h"
#include "Game.h"
#include "Sound.h"
#include "Back.h"
#include "Triangle.h"
//Little family
void ActNpc278(NPCHAR *npc)
{
RECT rcMama[2];
RECT rcPapa[2];
RECT rcKodomo[2];
rcPapa[0] = {0, 120, 8, 128};
rcPapa[1] = {8, 120, 16, 128};
rcMama[0] = {16, 120, 24, 128};
rcMama[1] = {24, 120, 32, 128};
rcKodomo[0] = {32, 120, 40, 128};
rcKodomo[1] = {40, 120, 48, 128};
switch (npc->act_no)
{
case 0:
npc->act_no = 1;
npc->ani_no = 0;
npc->ani_wait = 0;
npc->xm = 0;
// Fallthrough
case 1:
if (Random(0, 60) == 1)
{
npc->act_no = 2;
npc->act_wait = 0;
npc->ani_no = 1;
}
if (Random(0, 60) == 1)
{
npc->act_no = 10;
npc->act_wait = 0;
npc->ani_no = 1;
}
break;
case 2:
if (++npc->act_wait > 8)
{
npc->act_no = 1;
npc->ani_no = 0;
}
break;
case 10:
npc->act_no = 11;
npc->act_wait = Random(0, 16);
npc->ani_no = 0;
npc->ani_wait = 0;
if (Random(0, 9) % 2)
npc->direct = 0;
else
npc->direct = 2;
// Fallthrough
case 11:
if (npc->direct == 0 && (npc->flag & 1))
npc->direct = 2;
else if ( npc->direct == 2 && npc->flag & 4 )
npc->direct = 0;
if (npc->direct == 0)
npc->xm = -0x100;
else
npc->xm = 0x100;
if (++npc->ani_wait > 4)
{
npc->ani_wait = 0;
++npc->ani_no;
}
if (npc->ani_no > 1)
npc->ani_no = 0;
if (++npc->act_wait > 0x20)
npc->act_no = 0;
break;
}
npc->ym += 0x20;
if (npc->ym > 0x5FF)
npc->ym = 0x5FF;
npc->x += npc->xm;
npc->y += npc->ym;
switch (npc->code_event)
{
case 200:
npc->rect = rcPapa[npc->ani_no];
break;
case 210:
npc->rect = rcMama[npc->ani_no];
break;
default:
npc->rect = rcKodomo[npc->ani_no];
break;
}
}

View file

@ -80,11 +80,11 @@ NPCFUNCTION gpNpcFuncTbl[361] =
ActNpc021, ActNpc021,
ActNpc022, ActNpc022,
ActNpc023, ActNpc023,
nullptr, ActNpc024,
ActNpc025, ActNpc025,
nullptr, nullptr,
nullptr, nullptr,
nullptr, ActNpc028,
ActNpc029, ActNpc029,
ActNpc030, ActNpc030,
nullptr, nullptr,
@ -94,7 +94,7 @@ NPCFUNCTION gpNpcFuncTbl[361] =
nullptr, nullptr,
nullptr, nullptr,
ActNpc037, ActNpc037,
nullptr, ActNpc038,
ActNpc039, ActNpc039,
nullptr, nullptr,
nullptr, nullptr,
@ -116,8 +116,8 @@ NPCFUNCTION gpNpcFuncTbl[361] =
nullptr, nullptr,
ActNpc058, ActNpc058,
ActNpc059, ActNpc059,
nullptr, ActNpc060,
nullptr, ActNpc061,
ActNpc062, ActNpc062,
nullptr, nullptr,
ActNpc064, ActNpc064,
@ -125,7 +125,7 @@ NPCFUNCTION gpNpcFuncTbl[361] =
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, ActNpc069,
ActNpc070, ActNpc070,
ActNpc071, ActNpc071,
ActNpc072, ActNpc072,
@ -136,8 +136,8 @@ NPCFUNCTION gpNpcFuncTbl[361] =
ActNpc077, ActNpc077,
ActNpc078, ActNpc078,
ActNpc079, ActNpc079,
nullptr, ActNpc080,
nullptr, ActNpc081,
nullptr, nullptr,
ActNpc083, ActNpc083,
ActNpc084, ActNpc084,
@ -201,7 +201,7 @@ NPCFUNCTION gpNpcFuncTbl[361] =
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, ActNpc145,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
@ -334,7 +334,7 @@ NPCFUNCTION gpNpcFuncTbl[361] =
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
nullptr, ActNpc278,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,

View file

@ -129,7 +129,7 @@ float MillibelToVolume(int32_t lVolume)
{ {
//Volume is in hundredths of decibels, from 0 to -10000 //Volume is in hundredths of decibels, from 0 to -10000
lVolume = clamp(lVolume, (decltype(lVolume))-10000, (decltype(lVolume))0); lVolume = clamp(lVolume, (decltype(lVolume))-10000, (decltype(lVolume))0);
return pow(10.0f, lVolume / 2000.0f); return pow(10.0, lVolume / 2000.0);
} }
void SOUNDBUFFER::SetVolume(int32_t lVolume) void SOUNDBUFFER::SetVolume(int32_t lVolume)
@ -174,7 +174,7 @@ void SOUNDBUFFER::Stop()
SDL_UnlockAudioDevice(audioDevice); SDL_UnlockAudioDevice(audioDevice);
} }
void SOUNDBUFFER::Mix(float *buffer, int len) void SOUNDBUFFER::Mix(float (*buffer)[2], size_t samples)
{ {
if (this == NULL) if (this == NULL)
return; return;
@ -182,28 +182,24 @@ void SOUNDBUFFER::Mix(float *buffer, int len)
if (!playing) //This sound buffer isn't playing if (!playing) //This sound buffer isn't playing
return; return;
size_t samples = len / (sizeof(float) * 2);
for (size_t sample = 0; sample < samples; sample++) for (size_t sample = 0; sample < samples; sample++)
{ {
double freqPosition = (frequency / (double)FREQUENCY); //This is added to position at the end const double freqPosition = frequency / FREQUENCY; //This is added to position at the end
//Get the in-between sample this is (linear interpolation) //Get the in-between sample this is (linear interpolation)
uint8_t sample1 = ((looped || ((size_t)samplePosition) >= 1) ? data[(size_t)samplePosition] : 0x80); const float sample1 = ((looped || ((size_t)samplePosition) >= 1) ? data[(size_t)samplePosition] : 0x80);
uint8_t sample2 = 0x80; const float sample2 = ((looping || (((size_t)samplePosition) + 1) < size) ? data[(((size_t)samplePosition) + 1) % size] : 0x80);
if (looping || (((size_t)samplePosition) + 1) < size)
sample2 = data[(((size_t)samplePosition) + 1) % size];
//Interpolate sample //Interpolate sample
float subPos = std::fmod(samplePosition, 1.0); const float subPos = std::fmod(samplePosition, 1.0);
float sampleA = (float)sample1 + ((float)sample2 - (float)sample1) * subPos; const float sampleA = sample1 + (sample2 - sample1) * subPos;
//Convert sample to float32 //Convert sample to float32
float sampleConvert = (sampleA - 128.0) / 256.0; const float sampleConvert = (sampleA - 128.0f) / 128.0f;
//Mix //Mix
buffer[sample * 2] += sampleConvert * volume * volume_l; buffer[sample][0] += sampleConvert * volume * volume_l;
buffer[sample * 2 + 1] += sampleConvert * volume * volume_r; buffer[sample][1] += sampleConvert * volume * volume_r;
//Increment position //Increment position
samplePosition += freqPosition; samplePosition += freqPosition;
@ -229,14 +225,19 @@ void SOUNDBUFFER::Mix(float *buffer, int len)
//Sound mixer //Sound mixer
void AudioCallback(void *userdata, uint8_t *stream, int len) void AudioCallback(void *userdata, uint8_t *stream, int len)
{ {
float (*buffer)[2] = (float(*)[2])stream;
const size_t samples = len / (sizeof(float) * 2);
//Clear stream //Clear stream
memset(stream, 0, len); for (size_t sample = 0; sample < samples; ++sample)
{
buffer[sample][0] = 0.0f;
buffer[sample][1] = 0.0f;
}
//Mix sounds to primary buffer //Mix sounds to primary buffer
for (SOUNDBUFFER *sound = soundBuffers; sound != nullptr; sound = sound->next) for (SOUNDBUFFER *sound = soundBuffers; sound != nullptr; sound = sound->next)
{ sound->Mix(buffer, samples);
sound->Mix((float*)stream, len);
}
} }
//Sound things //Sound things

View file

@ -20,7 +20,7 @@ class SOUNDBUFFER
void Play(bool bLooping); void Play(bool bLooping);
void Stop(); void Stop();
void Mix(float *buffer, int len); void Mix(float (*buffer)[2], size_t samples);
SOUNDBUFFER *next; SOUNDBUFFER *next;