Skip to content

Commit

Permalink
Implement z-sorting for the sprites
Browse files Browse the repository at this point in the history
  • Loading branch information
rexim committed Jul 5, 2024
1 parent d5ede56 commit 57523a1
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 21 deletions.
23 changes: 15 additions & 8 deletions game.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 25 additions & 9 deletions game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -538,31 +538,47 @@ export interface Sprite {
position: Vector2;
z: number;
scale: number;

// Used only during the rendering. Initialize with 0.
// TODO: some sort of constructor that tucks all these away?
pdist: number; // Player distance.
t: number; // Normalized horizontal position on the screen
}

const visibleSprites: Array<Sprite> = [];
function renderSprites(display: Display, player: Player, sprites: Array<Sprite>) {
// TODO: z-sort the sprites
const markSize = 100;

const sp = new Vector2();
const dir = new Vector2().setAngle(player.direction);
const [p1, p2] = playerFovRange(player);

visibleSprites.length = 0;
for (const sprite of sprites) {
sp.copy(sprite.position).sub(player.position);
const spl = sp.length();
if (spl <= NEAR_CLIPPING_PLANE) continue; // Sprite is too close
if (spl >= FAR_CLIPPING_PLANE) continue; // Sprite is too far

const dot = sp.dot(dir)/spl;
// TODO: allow sprites to be slightly outside of FOV to make their edges visible
if (!(COS_OF_HALF_FOV <= dot)) continue; // Sprite is outside of the Field of View
const dist = NEAR_CLIPPING_PLANE/dot;
sp.norm().scale(dist).add(player.position);
const t = p1.distanceTo(sp)/p1.distanceTo(p2);
const cx = display.backImageData.width*t;
sprite.t = p1.distanceTo(sp)/p1.distanceTo(p2);
sprite.pdist = sprite.position.clone().sub(player.position).dot(dir);

// TODO: I'm not sure if these checks are necessary considering the `spl <= NEAR_CLIPPING_PLANE` above
if (sprite.pdist < NEAR_CLIPPING_PLANE) continue;
if (sprite.pdist >= FAR_CLIPPING_PLANE) continue;

visibleSprites.push(sprite);
}

visibleSprites.sort((a, b) => b.pdist - a.pdist);

for (let sprite of visibleSprites) {
const cx = display.backImageData.width*sprite.t;
const cy = display.backImageData.height*0.5;
const pdist = sprite.position.clone().sub(player.position).dot(dir);
if (pdist < NEAR_CLIPPING_PLANE) continue; // TODO: I'm not sure if this check is necessary considering the `spl <= NEAR_CLIPPING_PLANE` above
const maxSpriteSize = display.backImageData.height/pdist;
const maxSpriteSize = display.backImageData.height/sprite.pdist;
const spriteSize = maxSpriteSize*sprite.scale;
const x1 = Math.floor(cx - spriteSize*0.5);
const x2 = Math.floor(x1 + spriteSize - 1);
Expand All @@ -576,7 +592,7 @@ function renderSprites(display: Display, player: Player, sprites: Array<Sprite>)
const src = sprite.imageData.data;
const dest = display.backImageData.data;
for (let x = bx1; x <= bx2; ++x) {
if (pdist < display.zBuffer[x]) {
if (sprite.pdist < display.zBuffer[x]) {
for (let y = by1; y <= by2; ++y) {
const tx = Math.floor((x - x1)/spriteSize*sprite.imageData.width);
const ty = Math.floor((y - y1)/spriteSize*sprite.imageData.height);
Expand Down
38 changes: 36 additions & 2 deletions index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 41 additions & 2 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,48 @@ async function loadImageData(url: string): Promise<ImageData> {
const sprites = [
{
imageData: key,
position: new game.Vector2(1.5, 1.5),
position: new game.Vector2(2.5, 1.5),
z: KEY_Z,
scale: KEY_SCALE
scale: KEY_SCALE,

pdist: 0,
t: 0,
},
{
imageData: key,
position: new game.Vector2(3.0, 1.5),
z: KEY_Z,
scale: KEY_SCALE,

pdist: 0,
t: 0,
},
{
imageData: key,
position: new game.Vector2(3.5, 1.5),
z: KEY_Z,
scale: KEY_SCALE,

pdist: 0,
t: 0,
},
{
imageData: key,
position: new game.Vector2(4.0, 1.5),
z: KEY_Z,
scale: KEY_SCALE,

pdist: 0,
t: 0,
},
{
imageData: key,
position: new game.Vector2(4.5, 1.5),
z: KEY_Z,
scale: KEY_SCALE,

pdist: 0,
t: 0,
},
];

Expand Down
Binary file modified screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 57523a1

Please sign in to comment.