Initial commit: Western Shooter - Complete implementation
Retro western vertical shooter inspired by Gun.Smoke, built with TypeScript and WebGL2. Features 3-direction shooting, vertical scrolling, economy/shop loop, boss fights, and CRT shader effects. Phases implemented: - Phase 1: Engine skeleton (WebGL2 renderer, fixed timestep loop, input) - Phase 2: Shooting identity (3-dir shooting, bullet pools, collision) - Phase 3: Enemies & patterns (JSON waves, 4 enemy types, parallax bg) - Phase 4: Economy loop (pickups, shop, upgrades, HUD) - Phase 5: Boss system (3 bosses, wanted posters, multi-phase attacks) - Phase 6: Shader layer (CRT effects, bloom, scanlines, screen shake) - Phase 7: Performance (VAO batching, O(1) allocation, stress testing) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
export class Framebuffer {
|
||||
public readonly framebuffer: WebGLFramebuffer;
|
||||
public readonly texture: WebGLTexture;
|
||||
public readonly width: number;
|
||||
public readonly height: number;
|
||||
|
||||
constructor(gl: WebGL2RenderingContext, width: number, height: number) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
// Create texture for the framebuffer
|
||||
const texture = gl.createTexture();
|
||||
if (!texture) {
|
||||
throw new Error('Failed to create framebuffer texture');
|
||||
}
|
||||
this.texture = texture;
|
||||
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.texImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
0,
|
||||
gl.RGBA,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
gl.RGBA,
|
||||
gl.UNSIGNED_BYTE,
|
||||
null
|
||||
);
|
||||
|
||||
// Nearest-neighbor filtering for pixel-perfect upscaling
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
|
||||
// Create framebuffer
|
||||
const framebuffer = gl.createFramebuffer();
|
||||
if (!framebuffer) {
|
||||
throw new Error('Failed to create framebuffer');
|
||||
}
|
||||
this.framebuffer = framebuffer;
|
||||
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
||||
gl.framebufferTexture2D(
|
||||
gl.FRAMEBUFFER,
|
||||
gl.COLOR_ATTACHMENT0,
|
||||
gl.TEXTURE_2D,
|
||||
texture,
|
||||
0
|
||||
);
|
||||
|
||||
// Check framebuffer status
|
||||
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
||||
if (status !== gl.FRAMEBUFFER_COMPLETE) {
|
||||
throw new Error(`Framebuffer not complete: ${status}`);
|
||||
}
|
||||
|
||||
// Unbind
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||
}
|
||||
|
||||
bind(gl: WebGL2RenderingContext): void {
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
|
||||
gl.viewport(0, 0, this.width, this.height);
|
||||
}
|
||||
|
||||
unbind(gl: WebGL2RenderingContext): void {
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user