Untitled
unknown
plain_text
9 months ago
11 kB
11
Indexable
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Mini "Pokémon Yellow" Inspired Demo</title>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<style>
html,body{height:100%;margin:0;font-family:Arial,Helvetica,sans-serif;background:#f0f4f8}
.wrap{display:flex;gap:16px;align-items:flex-start;padding:16px}
canvas{background:#8fc3ff;border:4px solid #333;image-rendering:pixelated}
.ui{width:360px}
h1{margin:0 0 8px;font-size:18px}
.panel{background:#fff;border:1px solid #ccc;padding:8px;border-radius:6px;box-shadow:0 2px 6px rgba(0,0,0,.06)}
.controls small{color:#666}
button{padding:6px 10px;border-radius:6px;border:1px solid #888;background:#eee;cursor:pointer}
.log{height:220px;overflow:auto;font-size:13px;padding:8px;background:#111;color:#0f0;border-radius:4px}
</style>
</head>
<body>
<div class="wrap">
<div>
<canvas id="game" width="384" height="384"></canvas>
</div>
<div class="ui">
<div class="panel">
<h1>Mini Pokémon Yellow — Inspired Demo</h1>
<p>Move with arrow keys / WASD. Press <strong>Space</strong> to interact. Walk around to find wild encounters.</p>
<div style="display:flex;gap:8px;margin-top:8px">
<button id="btnStart">Reset</button>
<button id="btnBattle">Trigger Battle</button>
</div>
<div style="margin-top:10px">
<strong>Player</strong>: <span id="playerInfo">Level 5</span><br/>
<strong>Buddy</strong>: <span id="buddyInfo">Pika (happy)</span>
</div>
</div>
<div class="panel" style="margin-top:10px">
<h1>Battle Log</h1>
<div class="log" id="log"></div>
</div>
<div class="panel" style="margin-top:10px">
<h1>Notes</h1>
<ul style="margin:0 0 0 16px;padding:0">
<li>Everything here is drawable pixels — expand sprites freely.</li>
<li>Open the file locally in a browser. No server required.</li>
</ul>
</div>
</div>
</div>
<script>
/* -----------------------------
Tiny "Pokémon Yellow" inspired demo
- tile-based map (simple)
- player and buddy follow
- simple wild battle
----------------------------- */
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const tileSize = 32;
const cols = canvas.width / tileSize;
const rows = canvas.height / tileSize;
let state = {
player: {x: 6, y: 6, dir: 0, level: 5, hp: 20},
buddy: {x: 6, y: 7, mood: 'happy'},
map: [],
keys: {},
inBattle: false,
wild: null
};
const logEl = document.getElementById('log');
function log(s){ logEl.innerText = s + "\\n" + logEl.innerText; }
// simple map: 0 = grass, 1 = ground, 2 = tree, 3 = water
function generateMap(){
const m = [];
for(let y=0;y<rows;y++){
const row=[];
for(let x=0;x<cols;x++){
if (y<2 || y>rows-3 || x<2 || x>cols-3) row.push(2); // border trees
else {
// random grass patches
const r = Math.random();
if (r < 0.12) row.push(3);
else if (r < 0.45) row.push(0);
else row.push(1);
}
}
m.push(row);
}
// add a small house (walkable ground with a door)
for(let y=3;y<6;y++) for(let x=2;x<6;x++) m[y][x]=1;
m[5][3] = 1; // door area
return m;
}
function reset(){
state.map = generateMap();
state.player.x = 6; state.player.y = 6;
state.buddy.x = 6; state.buddy.y = 7; state.buddy.mood = 'happy';
state.inBattle = false; state.wild = null;
document.getElementById('playerInfo').innerText = `Level ${state.player.level}`;
document.getElementById('buddyInfo').innerText = `Pika (${state.buddy.mood})`;
log('Game reset.');
}
reset();
/* --- drawing helpers --- */
function drawTile(t,x,y){
const px = x*tileSize, py = y*tileSize;
if (t === 0) { // grass
ctx.fillStyle = '#7fc97f';
ctx.fillRect(px,py,tileSize,tileSize);
// little grass blades
ctx.fillStyle = '#5aa45a';
ctx.fillRect(px+6,py+22,2,4);
ctx.fillRect(px+18,py+20,2,5);
} else if (t === 1) { // ground
ctx.fillStyle = '#e6d3a3';
ctx.fillRect(px,py,tileSize,tileSize);
} else if (t === 2) { // tree
ctx.fillStyle = '#2f6b2f';
ctx.fillRect(px,py, tileSize, tileSize);
ctx.fillStyle = '#1f471f';
ctx.fillRect(px+6,py+6,20,10);
} else if (t === 3) { // water
ctx.fillStyle = '#4bb0dd';
ctx.fillRect(px,py,tileSize,tileSize);
ctx.fillStyle = '#3a97c0';
ctx.fillRect(px+4,py+18,16,3);
}
}
/* draw a simple player pixel sprite */
function drawPlayer(x,y){
const px = x*tileSize, py = y*tileSize;
// shadow
ctx.fillStyle = 'rgba(0,0,0,0.15)'; ctx.fillRect(px+8,py+24,16,6);
// body
ctx.fillStyle = '#222'; ctx.fillRect(px+12,py+8,8,12);
// jacket
ctx.fillStyle = '#c33'; ctx.fillRect(px+10,py+14,12,8);
// head
ctx.fillStyle = '#ffd79c'; ctx.fillRect(px+12,py+4,8,8);
}
/* buddy drawn as a tiny yellow creature */
function drawBuddy(x,y){
const px = x*tileSize, py = y*tileSize;
ctx.fillStyle = 'rgba(0,0,0,0.12)';
ctx.fillRect(px+10,py+26,12,4);
// yellow body
ctx.fillStyle = '#ffd400'; ctx.fillRect(px+10,py+10,12,12);
// ears
ctx.fillRect(px+9,py+6,3,6);
ctx.fillRect(px+18,py+6,3,6);
// cheeks
ctx.fillStyle = '#ff6b6b'; ctx.fillRect(px+11,py+16,3,3); ctx.fillRect(px+18,py+16,3,3);
// eyes
ctx.fillStyle = '#111'; ctx.fillRect(px+13,py+12,2,2); ctx.fillRect(px+17,py+12,2,2);
}
/* --- input --- */
window.addEventListener('keydown', e => {
state.keys[e.key.toLowerCase()] = true;
if (e.key === ' ') { e.preventDefault(); interact(); }
});
window.addEventListener('keyup', e => state.keys[e.key.toLowerCase()] = false);
/* --- simple collision: trees and water block movement --- */
function canWalk(x,y){
if (x<0||x>=cols||y<0||y>=rows) return false;
const t = state.map[y][x];
return t === 0 || t === 1; // grass or ground are walkable
}
/* --- movement & buddy follow --- */
let moveCooldown = 0;
function update(dt){
if (state.inBattle) return; // freeze world when in battle
moveCooldown -= dt;
if (moveCooldown <= 0){
let dx=0, dy=0;
if (state.keys['arrowup']||state.keys['w']) dy=-1;
else if (state.keys['arrowdown']||state.keys['s']) dy=1;
if (state.keys['arrowleft']||state.keys['a']) dx=-1;
else if (state.keys['arrowright']||state.keys['d']) dx=1;
if (dx!==0||dy!==0){
const nx = state.player.x + dx, ny = state.player.y + dy;
if (canWalk(nx,ny)){
state.player.x = nx; state.player.y = ny;
// buddy tries to follow: move toward player's old position
moveBuddyToward(state.player.x - dx, state.player.y - dy);
moveCooldown = 120; // ms between tile moves
// random encounter on grass
if (state.map[ny][nx] === 0 && Math.random() < 0.12) {
triggerWild();
}
}
}
}
}
/* buddy AI: simple pathing toward target tile (no A* for brevity) */
function moveBuddyToward(targetX, targetY){
const bx = state.buddy.x, by = state.buddy.y;
const dx = targetX - bx, dy = targetY - by;
let moved = false;
if (Math.abs(dx) > Math.abs(dy)){
const sx = Math.sign(dx);
if (canWalk(bx+sx,by)){ state.buddy.x += sx; moved = true; }
}
if (!moved && dy !== 0){
const sy = Math.sign(dy);
if (canWalk(bx,by+sy)){ state.buddy.y += sy; moved = true; }
}
if (!moved){
// stay put
}
}
/* --- rendering --- */
function render(){
ctx.clearRect(0,0,canvas.width,canvas.height);
// draw map
for(let y=0;y<rows;y++) for(let x=0;x<cols;x++) drawTile(state.map[y][x],x,y);
// draw player and buddy. Buddy follows and drawn before player so it may be behind/aside
drawBuddy(state.buddy.x, state.buddy.y);
drawPlayer(state.player.x, state.player.y);
// if in battle, overlay
if (state.inBattle && state.wild){
ctx.fillStyle = 'rgba(0,0,0,0.6)';
ctx.fillRect(0,0,canvas.width,canvas.height);
// battle box
ctx.fillStyle = '#fff'; ctx.fillRect(24,24,canvas.width-48,canvas.height-48);
ctx.strokeStyle = '#333'; ctx.strokeRect(24,24,canvas.width-48,canvas.height-48);
ctx.fillStyle = '#000'; ctx.font = '14px Arial';
ctx.fillText(`Wild ${state.wild.name} appeared!`, 40, 60);
ctx.fillText(`Wild HP: ${state.wild.hp}`, 40, 90);
ctx.fillText(`Your HP: ${state.player.hp}`, 40, 120);
ctx.fillText(`Press "A" to Attack, "R" to Run`, 40, 160);
}
}
/* --- very small battle system --- */
function triggerWild(){
// generate a tiny wild creature
const wilds = [
{name:'Pidgey-like', maxHp:8, atk:2},
{name:'Rattata-like', maxHp:6, atk:3},
{name:'Caterpie-like', maxHp:5, atk:1}
];
const pick = wilds[Math.floor(Math.random()*wilds.length)];
state.wild = {name: pick.name, hp: pick.maxHp, atk: pick.atk, maxHp: pick.maxHp};
state.inBattle = true;
log(`A wild ${state.wild.name} appeared!`);
// update info
document.getElementById('buddyInfo').innerText = `Pika (alert)`;
}
function battlePlayerAttack(){
if (!state.inBattle || !state.wild) return;
// player attack — trivial damage scaling by level
const dmg = Math.max(1, Math.floor(state.player.level * 0.8));
state.wild.hp -= dmg;
log(`You hit wild ${state.wild.name} for ${dmg} damage.`);
if (state.wild.hp <= 0){
log(`Wild ${state.wild.name} fainted! You won.`);
state.inBattle = false; state.wild = null;
document.getElementById('buddyInfo').innerText = `Pika (happy)`;
} else {
// wild attacks back
const dmg2 = state.wild.atk;
state.player.hp -= dmg2;
log(`${state.wild.name} hits you for ${dmg2} damage.`);
if (state.player.hp <= 0){
log(`You fainted! Resetting HP.`);
state.player.hp = Math.max(10, state.player.level * 4);
state.inBattle = false; state.wild = null;
document.getElementById('playerInfo').innerText = `Level ${state.player.level}`;
document.getElementById('buddyInfo').innerText = `Pika (sad)`;
}
}
}
/* user interact (space) triggers simple action if in front of player */
function interact(){
if (state.inBattle) return;
// check tile in front for "door"
const fx = state.player.x, fy = state.player.y;
// for demonstration: stepping on certain ground gives message
if (state.map[fy][fx] === 1){
log('This is soft ground. Your buddy naps a little.');
state.buddy.mood = 'sleepy';
document.getElementById('buddyInfo').innerText = `Pika (${state.buddy.mood})`;
} else {
log('Nothing interesting here.');
}
}
/* keyboard for battle */
window.addEventListener('keydown', e => {
if (!state.inBattle) return;
if (e.key.toLowerCase() === 'a'){ battlePlayerAttack(); }
if (e.key.toLowerCase() === 'r'){ // run
if (Math.random() < 0.6){ log('Got away safely!'); state.inBattle=false; state.wild=null; document.getElementById('buddyInfo').innerText = `Pika (relieved)`; }
else { log('Could not escape!'); const dmg2 = state.wild.atk; state.player.hp -= dmg2; log(`${state.wild.name} hits you for ${dmg2} damage.`); }
}
});
/* UI buttons */
document.getElementById('btnStart').onclick = reset;
document.getElementById('btnBattle').onclick = () => { if(!state.inBattle) triggerWild(); };
/* game loop */
let last = performance.now();
function loop(now){
const dt = now - last; last = now;
update(dt);
render();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
</script>
</body>
</html>
Editor is loading...
Leave a Comment