mirror of
https://gitlab.com/drummyfish/anarch.git
synced 2024-11-24 01:42:19 -05:00
Merge branch 'master' of https://codeberg.org/drummyfish/Anarch
This commit is contained in:
commit
fb3266d8cd
10
mods/README.txt
Normal file
10
mods/README.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ANARCH MODS
|
||||||
|
|
||||||
|
All mods here are created solely by drummyfish and released under the same terms
|
||||||
|
as Anarch, i.e. completely public domain (CC0).
|
||||||
|
|
||||||
|
Single file mods are right in this directory, multiple file mods are in their
|
||||||
|
own subdirectory.
|
||||||
|
|
||||||
|
Most mods are diffs and can easily be installed with "git apply", the suckless
|
||||||
|
way. The diffs sometimes have comments in them with details about the mod.
|
91
mods/crt.diff
Normal file
91
mods/crt.diff
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
This is a mod for Anarch that adds a simple CRT screen effect (scanlines plus
|
||||||
|
screen warp). By drummyfish.
|
||||||
|
|
||||||
|
diff --git a/game.h b/game.h
|
||||||
|
index 24285cb..4625ba1 100755
|
||||||
|
--- a/game.h
|
||||||
|
+++ b/game.h
|
||||||
|
@@ -816,24 +816,32 @@ uint16_t SFG_keyRegisters(uint8_t key)
|
||||||
|
return SFG_keyJustPressed(key) || SFG_keyRepeated(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
-#if SFG_RESOLUTION_SCALEDOWN == 1
|
||||||
|
- #define SFG_setGamePixel SFG_setPixel
|
||||||
|
-#else
|
||||||
|
+uint8_t SFG_screenWarpMap[SFG_GAME_RESOLUTION_X][SFG_GAME_RESOLUTION_Y];
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the game pixel (a pixel that can potentially be bigger than the screen
|
||||||
|
pixel).
|
||||||
|
*/
|
||||||
|
-static inline void SFG_setGamePixel(uint16_t x, uint16_t y, uint8_t colorIndex)
|
||||||
|
+static inline void SFG_setGamePixel(int16_t x, int16_t y, uint8_t colorIndex)
|
||||||
|
{
|
||||||
|
- uint16_t screenY = y * SFG_RESOLUTION_SCALEDOWN;
|
||||||
|
- uint16_t screenX = x * SFG_RESOLUTION_SCALEDOWN;
|
||||||
|
+ int16_t screenX = x - SFG_GAME_RESOLUTION_X / 2;
|
||||||
|
+ int16_t screenY = y - SFG_GAME_RESOLUTION_Y / 2;
|
||||||
|
+
|
||||||
|
+ uint8_t mul = SFG_screenWarpMap[x][y];
|
||||||
|
+
|
||||||
|
+ screenX = (screenX * mul) / 128;
|
||||||
|
+ screenY = (screenY * mul) / 128;
|
||||||
|
|
||||||
|
- for (uint16_t j = screenY; j < screenY + SFG_RESOLUTION_SCALEDOWN; ++j)
|
||||||
|
- for (uint16_t i = screenX; i < screenX + SFG_RESOLUTION_SCALEDOWN; ++i)
|
||||||
|
+ screenX = (screenX + SFG_GAME_RESOLUTION_X / 2) * SFG_RESOLUTION_SCALEDOWN;
|
||||||
|
+ screenY = (screenY + SFG_GAME_RESOLUTION_Y / 2) * SFG_RESOLUTION_SCALEDOWN;
|
||||||
|
+
|
||||||
|
+ // scanline effect:
|
||||||
|
+ colorIndex -= ((screenY / 2) % 2) && (colorIndex % 8 != 0);
|
||||||
|
+
|
||||||
|
+ for (int16_t j = screenY; j < screenY + SFG_RESOLUTION_SCALEDOWN; ++j)
|
||||||
|
+ for (int16_t i = screenX; i < screenX + SFG_RESOLUTION_SCALEDOWN; ++i)
|
||||||
|
SFG_setPixel(i,j,colorIndex);
|
||||||
|
}
|
||||||
|
-#endif
|
||||||
|
|
||||||
|
void SFG_recomputePLayerDirection()
|
||||||
|
{
|
||||||
|
@@ -1691,6 +1699,23 @@ void SFG_init()
|
||||||
|
SFG_game.cheatState = 0;
|
||||||
|
SFG_game.continues = 1;
|
||||||
|
|
||||||
|
+ for (int32_t y = 0; y < SFG_GAME_RESOLUTION_Y; ++y)
|
||||||
|
+ for (int32_t x = 0; x < SFG_GAME_RESOLUTION_X; ++x)
|
||||||
|
+ {
|
||||||
|
+ int32_t dx = x - SFG_GAME_RESOLUTION_X / 2;
|
||||||
|
+ dx = (dx * dx) / 512;
|
||||||
|
+
|
||||||
|
+ int32_t dy = y - SFG_GAME_RESOLUTION_Y / 2;
|
||||||
|
+ dy = (dy * dy) / 512;
|
||||||
|
+
|
||||||
|
+ SFG_screenWarpMap[x][y] = 128 -
|
||||||
|
+ ((dx + dy) * SFG_SCREEN_WARP) /
|
||||||
|
+ (
|
||||||
|
+ ((SFG_GAME_RESOLUTION_X * SFG_GAME_RESOLUTION_X) +
|
||||||
|
+ (SFG_GAME_RESOLUTION_Y * SFG_GAME_RESOLUTION_Y)) / (4 * 512)
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
RCL_initRayConstraints(&SFG_game.rayConstraints);
|
||||||
|
SFG_game.rayConstraints.maxHits = SFG_RAYCASTING_MAX_HITS;
|
||||||
|
SFG_game.rayConstraints.maxSteps = SFG_RAYCASTING_MAX_STEPS;
|
||||||
|
diff --git a/settings.h b/settings.h
|
||||||
|
index 2c8820a..663fcec 100644
|
||||||
|
--- a/settings.h
|
||||||
|
+++ b/settings.h
|
||||||
|
@@ -84,6 +84,13 @@
|
||||||
|
#define SFG_SCREEN_RESOLUTION_Y 600
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ Sets the amount of screen warp for the CRT simulation effect.
|
||||||
|
+*/
|
||||||
|
+#ifndef SFG_SCREEN_WARP
|
||||||
|
+ #define SFG_SCREEN_WARP 16
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
How quickly player turns left/right, in degrees per second.
|
||||||
|
*/
|
296
mods/makeMapImages.c
Normal file
296
mods/makeMapImages.c
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
/** Simple program to export Anarch maps as isometric images in PPM format.
|
||||||
|
The code is not very nice, the goal is just to get the images :)
|
||||||
|
|
||||||
|
by drummyfish, released under CC0 */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "../game.h"
|
||||||
|
|
||||||
|
#define IMAGE_W 4096 // if changed you also have to change PPM header data
|
||||||
|
#define IMAGE_H 2500
|
||||||
|
|
||||||
|
#define CENTER_X (IMAGE_W / 2)
|
||||||
|
#define CENTER_Y (IMAGE_H / 6)
|
||||||
|
|
||||||
|
#define TILE_H 25 // vertical height
|
||||||
|
#define TILE_TILT 2 // view angle, by how many H pixels we'll shift one down
|
||||||
|
|
||||||
|
unsigned char image[IMAGE_H * IMAGE_W * 3];
|
||||||
|
|
||||||
|
int maxHeights[4]; // ceiling limits for different quadrants
|
||||||
|
|
||||||
|
void drawPixel(int x, int y, unsigned char color, int multiply)
|
||||||
|
{
|
||||||
|
if (x < 0 || x >= IMAGE_W || y < 0 || y >= IMAGE_H)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint16_t rgb = paletteRGB565[color];
|
||||||
|
|
||||||
|
int index = (y * IMAGE_W + x) * 3;
|
||||||
|
|
||||||
|
image[index] = ((((rgb >> 11) << 3) & 0xff) * multiply) / 128;
|
||||||
|
image[index + 1] = ((((rgb >> 5) << 2) & 0xff) * multiply) / 128;
|
||||||
|
image[index + 2] = (((rgb << 3) & 0xff) * multiply) / 128;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawColum(int x, int y, int z1, int z2, int texture, int doorTexture, const uint8_t *sprite)
|
||||||
|
{
|
||||||
|
if (texture == SFG_TILE_TEXTURE_TRANSPARENT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int inc = z2 > z1 ? 1 : -1;
|
||||||
|
|
||||||
|
int minZ = z1 < z2 ? z1 : z2;
|
||||||
|
|
||||||
|
int brightness = (minZ / 2) % 128;
|
||||||
|
|
||||||
|
if (brightness < 0)
|
||||||
|
brightness *= -1;
|
||||||
|
|
||||||
|
brightness += 30;
|
||||||
|
|
||||||
|
for (int i = 0; i < SFG_TEXTURE_SIZE; ++i) // platform
|
||||||
|
for (int j = -1 * i / TILE_TILT; j <= i / TILE_TILT; ++j)
|
||||||
|
{
|
||||||
|
drawPixel(x + i,y + minZ + j,SFG_currentLevel.floorColor,brightness);
|
||||||
|
drawPixel(x + 2 * SFG_TEXTURE_SIZE - 1 - i,y + minZ + j,SFG_currentLevel.floorColor,brightness);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sprite != 0)
|
||||||
|
for (int sy = 0; sy < SFG_TEXTURE_SIZE; ++sy)
|
||||||
|
for (int sx = 0; sx < SFG_TEXTURE_SIZE; ++sx)
|
||||||
|
{
|
||||||
|
uint8_t color = SFG_getTexel(sprite,sx,sy);
|
||||||
|
|
||||||
|
if (color != SFG_TRANSPARENT_COLOR)
|
||||||
|
drawPixel(x + sx + SFG_TEXTURE_SIZE / 2,y + minZ + sy - SFG_TEXTURE_SIZE,color,110);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (z1 == z2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
z1 += inc;
|
||||||
|
|
||||||
|
int texY = 0;
|
||||||
|
|
||||||
|
while (z1 != z2) // column (walls)
|
||||||
|
{
|
||||||
|
int ty = (texY * SFG_TEXTURE_SIZE) / TILE_H;
|
||||||
|
|
||||||
|
uint8_t *t = (doorTexture < 0 || ty > SFG_TEXTURE_SIZE) ?
|
||||||
|
SFG_currentLevel.textures[texture] :
|
||||||
|
(SFG_wallTextures + doorTexture * SFG_TEXTURE_STORE_SIZE);
|
||||||
|
|
||||||
|
for (int i = 0; i < SFG_TEXTURE_SIZE; ++i)
|
||||||
|
{
|
||||||
|
uint8_t color = SFG_getTexel(t,i,ty);
|
||||||
|
|
||||||
|
if (color != SFG_TRANSPARENT_COLOR)
|
||||||
|
drawPixel(x + i,y + z1 + i / TILE_TILT,color,75);
|
||||||
|
|
||||||
|
color = SFG_getTexel(t,SFG_TEXTURE_SIZE - i,ty);
|
||||||
|
|
||||||
|
if (color != SFG_TRANSPARENT_COLOR)
|
||||||
|
drawPixel(x + 2 * SFG_TEXTURE_SIZE - 1 - i,y + z1 + i / TILE_TILT,
|
||||||
|
color,128);
|
||||||
|
}
|
||||||
|
|
||||||
|
texY++;
|
||||||
|
z1 += inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tileIndexToXY(int n, int *x, int *y)
|
||||||
|
{
|
||||||
|
int reverse = 0;
|
||||||
|
|
||||||
|
if (n > SFG_MAP_SIZE * SFG_MAP_SIZE / 2)
|
||||||
|
{
|
||||||
|
reverse = 1;
|
||||||
|
n = SFG_MAP_SIZE * SFG_MAP_SIZE - 1 - n;
|
||||||
|
}
|
||||||
|
|
||||||
|
*y = 0;
|
||||||
|
*x = 0;
|
||||||
|
|
||||||
|
while (*y < n)
|
||||||
|
{
|
||||||
|
*y += 1;
|
||||||
|
n -= *y;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (n > 0)
|
||||||
|
{
|
||||||
|
*x += 1;
|
||||||
|
*y -= 1;
|
||||||
|
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reverse)
|
||||||
|
{
|
||||||
|
*x = SFG_MAP_SIZE - 1 - *x;
|
||||||
|
*y = SFG_MAP_SIZE - 1 - *y;
|
||||||
|
}
|
||||||
|
|
||||||
|
*x = SFG_MAP_SIZE - 1 - *x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void exportMap(int index)
|
||||||
|
{
|
||||||
|
SFG_setAndInitLevel(index);
|
||||||
|
|
||||||
|
for (int i = 0; i < IMAGE_H * IMAGE_W * 3; ++i)
|
||||||
|
image[i] = 0;
|
||||||
|
|
||||||
|
unsigned char header[] =
|
||||||
|
{'P', '6', ' ', '4', '0', '9', '6', ' ', '2', '5', '0', '0', ' ',
|
||||||
|
'2', '5', '5', '\n'};
|
||||||
|
|
||||||
|
char fname[] = "map0.ppm";
|
||||||
|
|
||||||
|
fname[3] += index;
|
||||||
|
|
||||||
|
FILE *f = fopen(fname,"wb");
|
||||||
|
|
||||||
|
fwrite(header,sizeof(header),1,f);
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
for (int drawY = 0; drawY < SFG_MAP_SIZE; ++drawY)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
int xLimit = (1 + 2 * drawY + i);
|
||||||
|
|
||||||
|
if (drawY >= SFG_MAP_SIZE / 2)
|
||||||
|
xLimit = SFG_MAP_SIZE * 2 - xLimit;
|
||||||
|
|
||||||
|
#define TW (2 * SFG_TEXTURE_SIZE)
|
||||||
|
#define TH (SFG_TEXTURE_SIZE / TILE_TILT)
|
||||||
|
|
||||||
|
int startX = -1 * xLimit * TW / 2;
|
||||||
|
|
||||||
|
for (int drawX = 0; drawX < xLimit; ++drawX)
|
||||||
|
{
|
||||||
|
uint8_t properties;
|
||||||
|
int tx, ty;
|
||||||
|
|
||||||
|
tileIndexToXY(n,&tx,&ty);
|
||||||
|
|
||||||
|
int maxHeightTiles = maxHeights[2 * ((ty * 2) / SFG_MAP_SIZE) +
|
||||||
|
(tx * 2) / SFG_MAP_SIZE];
|
||||||
|
|
||||||
|
SFG_TileDefinition tile =
|
||||||
|
SFG_getMapTile(SFG_currentLevel.levelPointer,tx,ty,&properties);
|
||||||
|
|
||||||
|
int h = SFG_TILE_FLOOR_HEIGHT(tile);
|
||||||
|
|
||||||
|
if (properties == SFG_TILE_PROPERTY_ELEVATOR)
|
||||||
|
{
|
||||||
|
h += SFG_TILE_CEILING_HEIGHT(tile);
|
||||||
|
h /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxHeightTiles * 4 < h)
|
||||||
|
h = maxHeightTiles * 4;
|
||||||
|
|
||||||
|
h = (h * SFG_WALL_HEIGHT_STEP * TILE_H) / RCL_UNITS_PER_SQUARE;
|
||||||
|
|
||||||
|
const uint8_t *sprite = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < SFG_MAX_LEVEL_ELEMENTS; ++i)
|
||||||
|
{
|
||||||
|
SFG_LevelElement e =
|
||||||
|
SFG_currentLevel.levelPointer->elements[i];
|
||||||
|
|
||||||
|
if (e.type == SFG_LEVEL_ELEMENT_NONE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (e.coords[0] == tx && e.coords[1] == ty && !(e.type & 0x10))
|
||||||
|
{
|
||||||
|
uint8_t ss;
|
||||||
|
|
||||||
|
if (e.type & 0x20)
|
||||||
|
sprite = SFG_getMonsterSprite(e.type,0,0);
|
||||||
|
else
|
||||||
|
SFG_getItemSprite(e.type,&sprite,&ss);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawColum(
|
||||||
|
CENTER_X + startX + drawX * TW,
|
||||||
|
CENTER_Y + (2 * drawY + i) * TH - drawY,-1 * h,
|
||||||
|
0,SFG_TILE_FLOOR_TEXTURE(tile),
|
||||||
|
(properties == SFG_TILE_PROPERTY_DOOR) ?
|
||||||
|
SFG_currentLevel.levelPointer->doorTextureIndex : -1,
|
||||||
|
sprite);
|
||||||
|
|
||||||
|
int maxH = 16 * TILE_H;
|
||||||
|
|
||||||
|
if (maxHeightTiles * TILE_H < maxH)
|
||||||
|
maxH = maxHeightTiles * TILE_H;
|
||||||
|
|
||||||
|
maxH *= -1;
|
||||||
|
|
||||||
|
h = SFG_TILE_FLOOR_HEIGHT(tile) + SFG_TILE_CEILING_HEIGHT(tile);
|
||||||
|
h = -1 * (h * SFG_WALL_HEIGHT_STEP * TILE_H) / RCL_UNITS_PER_SQUARE + 1;
|
||||||
|
|
||||||
|
if (SFG_TILE_CEILING_HEIGHT(tile) < 31 &&
|
||||||
|
maxH < h && properties != SFG_TILE_PROPERTY_ELEVATOR)
|
||||||
|
{
|
||||||
|
drawColum(
|
||||||
|
CENTER_X + startX + drawX * TW,
|
||||||
|
CENTER_Y + (2 * drawY + i) * TH - drawY,maxH,
|
||||||
|
h,SFG_TILE_CEILING_TEXTURE(tile),-1,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(image,1,IMAGE_W * IMAGE_H * 3,f);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
SFG_init();
|
||||||
|
|
||||||
|
#define E(m,h1,h2,h3,h4)\
|
||||||
|
printf("exporting %d\n",m);\
|
||||||
|
maxHeights[0] = h1;\
|
||||||
|
maxHeights[1] = h2;\
|
||||||
|
maxHeights[2] = h3;\
|
||||||
|
maxHeights[3] = h4;\
|
||||||
|
exportMap(m);
|
||||||
|
|
||||||
|
E(0,100,100,100,100)
|
||||||
|
E(1,7,5,7,5)
|
||||||
|
E(2,5,6,5,5)
|
||||||
|
E(3,7,7,6,6)
|
||||||
|
E(4,100,6,100,6)
|
||||||
|
E(5,100,100,100,100)
|
||||||
|
E(6,5,4,3,3)
|
||||||
|
E(7,7,7,7,7)
|
||||||
|
E(8,5,5,5,5)
|
||||||
|
E(9,100,100,100,100)
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// just create empty functions, game.h requires it:
|
||||||
|
int8_t SFG_keyPressed(uint8_t key) { return 0; }
|
||||||
|
void SFG_getMouseOffset(int16_t *x, int16_t *y) { }
|
||||||
|
uint32_t SFG_getTimeMs() { return 0; }
|
||||||
|
void SFG_sleepMs(uint16_t timeMs) { }
|
||||||
|
static inline void SFG_setPixel(uint16_t x, uint16_t y, uint8_t colorIndex) { }
|
||||||
|
void SFG_playSound(uint8_t soundIndex, uint8_t volume) { }
|
||||||
|
void SFG_setMusic(uint8_t value) { }
|
||||||
|
void SFG_processEvent(uint8_t event, uint8_t data) { }
|
||||||
|
void SFG_save(uint8_t data[SFG_SAVE_SIZE]) { }
|
||||||
|
uint8_t SFG_load(uint8_t data[SFG_SAVE_SIZE]) { return 0; }
|
Loading…
Reference in New Issue
Block a user