像素农夫物语 V9 手动自动等级升级完整版
by BraveDragon92995 lines43.7 KB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>像素农夫物语 V9 手动自动等级升级完整版</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
image-rendering: pixelated;
font-family: "Courier New", monospace;
}
body {
background: #222;
display: flex;
flex-direction: column;
align-items: center;
padding: 10px;
color: #fff;
}
#gameBox {
border: 4px solid #884400;
background: #58a6ff;
width: 800px;
height: 500px;
position: relative;
overflow: hidden;
}
canvas {
display: block;
}
.ui-panel {
width: 800px;
background: #333;
padding: 8px 12px;
display: flex;
justify-content: space-between;
align-items: center;
border: 2px solid #555;
gap:8px;
flex-wrap:wrap;
margin-bottom:6px;
}
.btn {
padding: 6px 12px;
background: #ffcc00;
color: #000;
border: none;
font-weight: bold;
cursor: pointer;
font-size: 14px;
image-rendering: pixelated;
}
.btn-danger {background: #ff4444; color:#fff;}
.btn-green {background: #44dd44; color:#000;}
.btn-blue {background:#66aaff;color:#000}
.btn-purple {background:#aa44ff;color:#fff}
.btn-orange {background:#ff7722;color:#fff;}
.btn-sm {
padding:3px 8px;
font-size:12px;
}
.mask {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0,0,0,0.7);
z-index: 9999;
display: none;
}
.modal-box {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #2a2a2a;
border: 4px solid #ffcc00;
z-index: 10000;
display: none;
}
.modal-header {
display:flex;
justify-content: space-between;
align-items:center;
padding:10px 12px;
border-bottom: 2px solid #444;
}
.header-btn-group {
display:flex;
gap:6px;
flex-wrap:wrap;
}
.shop-body {
max-height: 320px;
overflow-y: auto;
padding:10px 12px;
}
.shop-panel {width:620px;}
.setting-panel {min-width: 520px;}
.house-panel {min-width:360px;text-align:center;padding:20px 16px;}
.shop-item {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid #555;
}
.version-desc {
font-size:12px;
color:#ccc;
margin:8px 0 16px;
line-height:1.4;
}
</style>
</head>
<body>
<h2>8bit像素农夫 V9(多存档+宠物升级+手动自动等级升级)</h2>
<div class="ui-panel">
<div>
等级:<span id="lv">1</span> | 升级所需金币:<span id="lvNeed">2000</span>
| 金币:<span id="gold">0</span> | 田地数:<span id="landNum">4</span>
</div>
<div>
宠物:<span id="petCount">0</span> | 佣人:<span id="servantCount">0</span>
| 冥界种子:<span id="seedNether">0</span> | 生命树种子:<span id="seedLife">0</span>
</div>
<div>
天使之力:<span id="buffAngel">无</span> | 黑暗之力:<span id="buffDark">无</span>
| 时段:<span id="dayPhase">白天</span>
</div>
<div class="header-btn-group">
<button class="btn btn-orange" onclick="manualLevelUp()">手动升级</button>
<button class="btn btn-orange" id="autoLvBtn" onclick="toggleAutoLevel()">自动升级:关闭</button>
<button class="btn" onclick="openShop()">商店</button>
<button class="btn btn-green" onclick="openSetting()">切换版本</button>
</div>
</div>
<div id="gameBox">
<canvas id="gameCanvas" width="800" height="500"></canvas>
</div>
<div class="mask" id="mask" onclick="closeAllPopup()"></div>
<div class="modal-box shop-panel" id="shopBox" onclick="event.stopPropagation()">
<div class="modal-header">
<h3>像素商店(V9解锁宠物升级)</h3>
<div class="header-btn-group">
<button class="btn btn-sm btn-blue" onclick="saveSlot(1)">存档1</button>
<button class="btn btn-sm btn-blue" onclick="loadSlot(1)">读档1</button>
<button class="btn btn-sm btn-blue" onclick="saveSlot(2)">存档2</button>
<button class="btn btn-sm btn-blue" onclick="loadSlot(2)">读档2</button>
<button class="btn btn-sm btn-blue" onclick="saveSlot(3)">存档3</button>
<button class="btn btn-sm btn-blue" onclick="loadSlot(3)">读档3</button>
<button class="btn btn-sm btn-green" onclick="backOriginWorld()">返回主世界</button>
<button class="btn btn-sm" onclick="goHell()">地狱(LV3)</button>
<button class="btn btn-sm btn-purple" onclick="goHeaven()">天堂(LV5)</button>
<button class="btn btn-sm btn-danger" onclick="closeShop()">关闭</button>
</div>
</div>
<div class="shop-body" id="shopList"></div>
</div>
<div class="modal-box setting-panel" id="settingBox" onclick="event.stopPropagation()">
<div class="modal-header">
<h3>版本切换</h3>
<div class="header-btn-group">
<button class="btn btn-sm btn-danger" onclick="closeSetting()">关闭</button>
</div>
</div>
<div style="padding:10px 12px;">
<div class="version-desc">
V1远古|V2工业|V3异界|V4完整|V5冥界|V6天堂|V7佣人小屋基础|V8终极|V9宠物升级完整版
<br>V9新增:宠物升级、附魔词条、3组独立存档、天堂LV5解锁、盗贼上限4只、修复小偷拖尾、成熟作物永久保留、手动/自动等级升级
</div>
<div>
<button class="btn" onclick="switchVer(1)">V1</button><br><br>
<button class="btn" onclick="switchVer(2)">V2</button><br><br>
<button class="btn" onclick="switchVer(3)">V3</button><br><br>
<button class="btn" onclick="switchVer(4)">V4</button><br><br>
<button class="btn" onclick="switchVer(5)">V5</button><br><br>
<button class="btn" onclick="switchVer(6)">V6</button><br><br>
<button class="btn" onclick="switchVer(7)">V7</button><br><br>
<button class="btn" onclick="switchVer(8)">V8</button><br><br>
<button class="btn" onclick="switchVer(9)">V9 宠物升级完整版</button><br><br>
</div>
</div>
</div>
<div class="modal-box house-panel" id="houseBox" onclick="event.stopPropagation()">
<div class="modal-header">
<h3>自家小屋</h3>
<div class="header-btn-group">
<button class="btn btn-sm btn-danger" onclick="closeHouse()">离开</button>
</div>
</div>
<div>
<p style="margin:12px 0;">请选择你要做的事</p>
<button class="btn" onclick="eatMeal()">吃饭休息</button><br><br>
<button class="btn" onclick="sleepNight()">上床睡觉,跳过黑夜</button><br><br>
</div>
</div>
<p style="margin-top:8px;">规则:昼夜循环;早午晚餐强制食用,夜宵可拒绝;佣人仅V8/V9生效;V9宠物可升级附魔,等级越高体型变大;附魔稀有度:附魔之力>天使增幅>黑暗增幅>攻速>攻击;天堂LV5解锁;盗贼最多4只;3组本地存档永久保存;升级仅可手动点击或开启自动升级扣钱提升</p>
<script>
const ctx = document.getElementById('gameCanvas').getContext('2d');
// ========== 全局变量 ==========
let gameVer = 1;
let gold = 0;
let level = 1;
let landMax = 4;
let landList = [];
let player = {x:380,y:320,w:44,h:64};
let hellOpen = false;
let heavenOpen = false;
let isHellMap = false;
let isHeavenMap = false;
let bandits = [];
const MAX_BANDIT = 4;
let hasWeapon = false;
let hasMachine = false;
let tick = 0;
let pets = [];
let servants = [];
let netherSeed = 0;
let lifeTreeSeed = 0;
let buffAngel = false;
let buffDark = false;
let buffEat = false;
let buffEatTick = 0;
let heavenSeedPick = null;
let heavenParticles = [];
let dayCycleTick = 0;
const DAY_CYCLE_LEN = 2400;
let dayPhase = "day";
let mealFlagMorning = false;
let mealFlagNoon = false;
let mealFlagDinner = false;
let mealFlagMidnight = false;
let gamePause = false;
const housePos = {x:20,y:330,w:90,h:70};
const isWin7Win8 = Math.random() < 0.5;
const LIFE_TREE_GROW_CHANCE = isWin7Win8 ? 1 : 0.0001;
const NETHER_SPAWN_CHANCE = isWin7Win8 ? 0.5 : 0.12;
const ENCHANT_LIST = ["附魔之力","天使增幅","黑暗增幅","攻速提升","攻击强化"];
let autoLevelSwitch = false;
// ========== 等级升级核心函数 ==========
function getLevelNeed(){
return 2000 * (2 ** (level - 1));
}
function manualLevelUp(){
const cost = getLevelNeed();
if(gold >= cost){
gold -= cost;
level += 1;
alert(`升级成功!当前等级${level},下一级需要${getLevelNeed()}金币`);
}else{
alert(`金币不足!升级需要${cost}金币,还差${cost - gold}`);
}
}
function toggleAutoLevel(){
autoLevelSwitch = !autoLevelSwitch;
const btn = document.getElementById("autoLvBtn");
if(autoLevelSwitch){
btn.innerText = "自动升级:开启";
btn.style.background = "#22dd22";
}else{
btn.innerText = "自动升级:关闭";
btn.style.background = "#ff7722";
}
}
// ========== 常量定义 ==========
const PET_TYPE = {WOLF:0,HUSKY:1,CAT:2,PIG:3,COW:4,SHEEP:5}
const CROP_TYPE = {WHEAT:0,FRUIT_TREE:1,WILD_GRASS:2,WILD_FLOWER:3,NETHER_FLOWER:4,NETHER_TREE:5,LIFE_TREE:6}
const PALETTE = {
skyDay: "#58a6ff", skyDayGrad: "#87ceff",
skyDusk: "#ff8855", skyDuskGrad: "#ffdd88",
skyNight: "#101030", skyNightGrad: "#302060",
heavenSky: "#e0f0ff", heavenSkyGrad: "#ffffff",
hellSky: "#6b0000", hellSkyGrad: "#aa2222",
ground: "#8b5a2b", grass: "#38b000", grassDark: "#2d8800",
hellGround: "#2e1010", hellGrass: "#4a1515", hellPlant: "#ff2266",
heavenGround: "#e6edf7", heavenGrass: "#d0e0f5", heavenCrop: "#f8ffff", heavenSilver:"#c8e8f8",
farmerSkin: "#ffdab9", farmerHair: "#8b4513", farmerCloth: "#ff0000", farmerOveralls: "#0066cc", farmerShoes: "#333333",
crop: "#ffcc00", cropStem: "#8b4513", bandit: "#2b2b2b", banditMask: "#ff0000",
wolf: "#a0a0a0", hellHound: "#ff2222", husky: "#d0e8ff", hellHusky: "#ff6600",
cat: "#ffc0cb", hellCat: "#9900cc", pig: "#ff9999", hellPig: "#771111", cow: "#996633", hellCow: "#442211", sheep: "#ffffff", hellSheep: "#bbbbbb",
fruitTree: "#ff9933", wildGrass: "#77dd22", wildFlower: "#ff77bb", netherFlower: "#cc0066", netherTree: "#990022", netherFruit: "#ff0044", lifeTree: "#ffffff", lifeFruit:"#fff8cc",
houseWall:"#ddaa77", houseRoof:"#883322", houseDoor:"#552211", servant:"#fff2cc"
}
// ========== 初始化 ==========
function initLand(){
landList = [];
let xStart = 120;
for(let i=0;i<landMax;i++){
landList.push({
x:xStart + i*80, y:380, w:70, h:80,
seed:false, grow:0, full:false, isHellCrop:false, stolen:false, cropType:CROP_TYPE.WHEAT,
harvested: false
})
}
heavenSeedPick = null;
heavenParticles = [];
}
function switchVer(v){
gameVer = v;
hellOpen = v>=3;
heavenOpen = v>=6;
closeAllPopup();
alert(`切换至 V${v}`);
initLand();
bandits = [];
pets = [];
servants = [];
netherSeed = 0;
lifeTreeSeed = 0;
buffAngel = false;
buffDark = false;
buffEat = false;
dayCycleTick = 0;
mealFlagMorning = false;
mealFlagNoon = false;
mealFlagDinner = false;
mealFlagMidnight = false;
autoLevelSwitch = false;
const btn = document.getElementById("autoLvBtn");
btn.innerText = "自动升级:关闭";
btn.style.background = "#ff7722";
}
// ========== 绘制工具 ==========
function drawPixelRect(x,y,w,h,color){
ctx.fillStyle = color;
ctx.fillRect(Math.floor(x),Math.floor(y),w,h);
}
function drawCloud(x,y){
drawPixelRect(x+4,y,32,16,"#ffffff");
drawPixelRect(x,y+8,40,12,"#ffffff");
}
function drawHouse(){
if(gameVer <8) return;
let h = housePos;
drawPixelRect(h.x+8,h.y+20,h.w-16,h.h-20,PALETTE.houseWall);
drawPixelRect(h.x,h.y,h.w,24,PALETTE.houseRoof);
drawPixelRect(h.x+32,h.y+32,24,38,PALETTE.houseDoor);
drawPixelRect(h.x+14,h.y+28,14,14,"#aaddff");
drawPixelRect(h.x+62,h.y+28,14,14,"#aaddff");
}
function drawFarmer(){
const p = player;
drawPixelRect(p.x+10, p.y, 24,24, PALETTE.farmerSkin);
drawPixelRect(p.x+8, p.y-4,28,10, PALETTE.farmerHair);
drawPixelRect(p.x+12, p.y+8,5,5,"#000");
drawPixelRect(p.x+26, p.y+8,5,5,"#000");
drawPixelRect(p.x+16, p.y+18,12,3,"#cc6666");
drawPixelRect(p.x+6, p.y+24,32,26, PALETTE.farmerOveralls);
drawPixelRect(p.x+10, p.y+26,24,8, PALETTE.farmerCloth);
drawPixelRect(p.x+8, p.y+50,12,14, PALETTE.farmerShoes);
drawPixelRect(p.x+24, p.y+50,12,14, PALETTE.farmerShoes);
drawPixelRect(p.x+36, p.y+30,10,6,"#ffdab9");
}
// ========== 田地作物绘制 ==========
function drawLand(){
landList.forEach(land=>{
let gColor;
if(isHeavenMap) gColor = PALETTE.heavenGround;
else if(isHellMap) gColor = PALETTE.hellGround;
else gColor = PALETTE.ground;
drawPixelRect(land.x,land.y,land.w,land.h,gColor);
ctx.strokeStyle="#222";
ctx.lineWidth=2;
ctx.strokeRect(land.x,land.y,land.w,land.h);
if(land.seed && !land.stolen){
let plantH = land.full ? 7 * 14 : land.grow * 14;
let stemColor,fruitColor;
if(isHeavenMap){
stemColor="#e8f4ff";
fruitColor = land.cropType === CROP_TYPE.LIFE_TREE ? PALETTE.lifeTree : PALETTE.heavenCrop;
}else if(isHellMap && gameVer >=5){
if(land.cropType === CROP_TYPE.NETHER_FLOWER){
stemColor="#660033";fruitColor=PALETTE.netherFlower;
}else if(land.cropType === CROP_TYPE.NETHER_TREE){
stemColor="#440011";fruitColor=PALETTE.netherTree;
}else{
stemColor="#880033";fruitColor=PALETTE.hellPlant;
}
}else{
switch(land.cropType){
case CROP_TYPE.WHEAT: stemColor=PALETTE.cropStem;fruitColor=PALETTE.crop;break;
case CROP_TYPE.FRUIT_TREE: stemColor="#553311";fruitColor=PALETTE.fruitTree;break;
case CROP_TYPE.WILD_GRASS: stemColor="#227711";fruitColor=PALETTE.wildGrass;break;
case CROP_TYPE.WILD_FLOWER: stemColor="#338822";fruitColor=PALETTE.wildFlower;break;
default: stemColor=PALETTE.cropStem;fruitColor=PALETTE.crop;
}
}
drawPixelRect(land.x+34, land.y - plantH, 6, plantH, stemColor);
drawPixelRect(land.x+28, land.y - plantH - 12, 14, 16, fruitColor);
drawPixelRect(land.x+30, land.y - plantH - 18,10,8,isHeavenMap?"#ffffff":"#ffff00");
}
if(land.stolen) drawPixelRect(land.x+20, land.y-30,30,8,"#ff0000");
})
}
// ========== 盗贼系统 ==========
function spawnBandit(){
if(gamePause) return;
if(gameVer >=4 && tick % 600 === 0 && bandits.length < MAX_BANDIT){
bandits.push({x:750, y:360, w:36, h:50, hp:2, targetLand:null})
}
}
function banditStealLogic(){
if(gamePause) return;
if(gameVer <4) return;
bandits.forEach(bandit=>{
if(pets.length > 0) return;
if(!bandit.targetLand || bandit.targetLand.stolen || !bandit.targetLand.full){
bandit.targetLand = null;
for(let l of landList){if(l.full && !l.stolen){bandit.targetLand = l;break;}}
}
if(bandit.targetLand){
let tar = bandit.targetLand;
let dx = tar.x - bandit.x;
bandit.x += dx > 0 ? 0.6 : -0.6;
if(Math.abs(bandit.x - tar.x) < 30){
tar.stolen = true; tar.seed = false; tar.full = false;
}
}
})
}
function drawBandits(){
bandits.forEach(b=>{
drawPixelRect(b.x+8,b.y,20,20,PALETTE.bandit);
drawPixelRect(b.x+6,b.y+20,24,18,"#880000");
drawPixelRect(b.x+10,b.y+6,16,6,PALETTE.banditMask);
drawPixelRect(b.x+12,b.y+8,4,3,"#fff");
drawPixelRect(b.x+20,b.y+8,4,3,"#fff");
drawPixelRect(b.x+10,b.y+38,6,12,"#111");
drawPixelRect(b.x+20,b.y+38,6,12,"#111");
})
}
// ========== 宠物系统 ==========
function petAttackBandit(){
if(gamePause) return;
if(gameVer <4 || bandits.length ===0 || pets.length ===0) return;
for(let pet of pets){
if(isHellMap && pet.type === PET_TYPE.HUSKY){
bandits.forEach(b=>{
pet.exp += 30;
if(gameVer >=9) checkPetLevelUp(pet);
});
bandits = [];
gold += 500;
return;
}
}
}
function checkPetLevelUp(pet){
const expNeed = pet.level * 100;
if(pet.exp >= expNeed){
pet.exp -= expNeed;
pet.level += 1;
let roll = Math.random();
let enchant;
if(roll < 0.08) enchant = "附魔之力";
else if(roll < 0.28) enchant = "天使增幅";
else if(roll < 0.48) enchant = "黑暗增幅";
else if(roll < 0.72) enchant = "攻速提升";
else enchant = "攻击强化";
pet.enchant = enchant;
alert(`宠物升级!当前等级${pet.level},获得词条:${enchant}`);
}
}
function createPet(type){
let posX = 100 + pets.length * 90;
pets.push({
x: posX, y: 390, w:32, h:36, tickOff: Math.random()*100, type: type,
level:1, exp:0, enchant:"无"
})
}
function drawSinglePet(pet){
pet.tickOff++;
let bounce = Math.sin(pet.tickOff * 0.08) * 3;
let py = pet.y + bounce;
let t = pet.type;
let baseColor, hellColor, eyeColor = "#000";
let lvMod = Math.min(pet.level,5);
switch(t){
case PET_TYPE.WOLF: baseColor = PALETTE.wolf; hellColor = PALETTE.hellHound; break;
case PET_TYPE.HUSKY: baseColor = PALETTE.husky; hellColor = PALETTE.hellHusky; break;
case PET_TYPE.CAT: baseColor = PALETTE.cat; hellColor = PALETTE.hellCat; break;
case PET_TYPE.PIG: baseColor = PALETTE.pig; hellColor = PALETTE.hellPig; break;
case PET_TYPE.COW: baseColor = PALETTE.cow; hellColor = PALETTE.hellCow; break;
case PET_TYPE.SHEEP: baseColor = PALETTE.sheep; hellColor = PALETTE.hellSheep; break;
}
let c = isHellMap ? hellColor : baseColor;
let scale = 1 + lvMod * 0.08;
let off = (32 - 32*scale)/2;
drawPixelRect(pet.x+6+off, py+10+off,20*scale,18*scale, c);
if(t === PET_TYPE.WOLF){
drawPixelRect(pet.x+off, py+off,8*scale,10*scale,c); drawPixelRect(pet.x+24+off, py+off,8*scale,10*scale,c);
drawPixelRect(pet.x+8+off, py+8+off,4*scale,4*scale,eyeColor); drawPixelRect(pet.x+18+off, py+8+off,4*scale,4*scale,eyeColor);
if(isHellMap){drawPixelRect(pet.x+2+off, py+2+off,3*scale,3*scale,"#ff0000");drawPixelRect(pet.x+26+off, py+2+off,3*scale,3*scale,"#ff0000");}
}else if(t === PET_TYPE.HUSKY){
drawPixelRect(pet.x+2+off, py+off,28*scale,12*scale,c);
drawPixelRect(pet.x+6+off, py+6+off,4*scale,4*scale,eyeColor); drawPixelRect(pet.x+22+off, py+6+off,4*scale,4*scale,eyeColor);
drawPixelRect(pet.x+14+off, py+2+off,4*scale,4*scale,"#333");
if(isHellMap){drawPixelRect(pet.x+4+off, py+4+off,3*scale,3*scale,"#ff0000");drawPixelRect(pet.x+24+off, py+4+off,3*scale,3*scale,"#ff0000");}
}else if(t === PET_TYPE.CAT){
drawPixelRect(pet.x+4+off, py+off,24*scale,10*scale,c);
drawPixelRect(pet.x+8+off, py+6+off,3*scale,3*scale,eyeColor); drawPixelRect(pet.x+18+off, py+6+off,3*scale,3*scale,eyeColor);
drawPixelRect(pet.x+2+off, py-4+off,6*scale,6*scale,c); drawPixelRect(pet.x+24+off, py-4+off,6*scale,6*scale,c);
}else if(t === PET_TYPE.PIG){
drawPixelRect(pet.x+8+off, py+off,16*scale,12*scale,c); drawPixelRect(pet.x+10+off, py+8+off,6*scale,4*scale,"#ff6666");
drawPixelRect(pet.x+12+off, py+4+off,3*scale,3*scale,eyeColor); drawPixelRect(pet.x+18+off, py+4+off,3*scale,3*scale,eyeColor);
}else if(t === PET_TYPE.COW){
drawPixelRect(pet.x+4+off, py+off,24*scale,14*scale,c);
drawPixelRect(pet.x+6+off, py+6+off,4*scale,4*scale,"#fff"); drawPixelRect(pet.x+18+off, py+6+off,4*scale,4*scale,"#fff");
drawPixelRect(pet.x+2+off, py+2+off,6*scale,6*scale,"#ffffff"); drawPixelRect(pet.x+24+off, py+2+off,6*scale,6*scale,"#ffffff");
}else if(t === PET_TYPE.SHEEP){
drawPixelRect(pet.x+4+off, py+off,24*scale,14*scale,c);
drawPixelRect(pet.x+8+off, py+6+off,3*scale,3*scale,eyeColor); drawPixelRect(pet.x+18+off, py+6+off,3*scale,3*scale,eyeColor);
drawPixelRect(pet.x+6+off, py+12+off,20*scale,4*scale,"#dddddd");
}
drawPixelRect(pet.x+8+off, py+28+off,6*scale,8*scale,"#333"); drawPixelRect(pet.x+18+off, py+28+off,6*scale,8*scale,"#333");
}
function drawPets(){
if(gameVer <3) return;
pets.forEach(p=>drawSinglePet(p));
document.getElementById('petCount').innerText = pets.length;
}
// ========== 佣人系统 ==========
function createServant(){
servants.push({x: 90 + servants.length * 75, y:392, w:28, h:32, tick:0})
}
function servantAutoHarvest(){
if(gamePause) return;
if(gameVer !== 8 && gameVer !==9 || servants.length ===0) return;
servants.forEach(s=>{
s.tick++;
if(s.tick >=60){
s.tick = 0;
for(let l of landList){
if(l.full && !l.stolen && !l.harvested){
l.harvested = true;
let earn = l.isHellCrop ? 400 : 200;
if(l.cropType === CROP_TYPE.LIFE_TREE){
gold += 1000; buffAngel = true;
}else if(l.cropType === CROP_TYPE.NETHER_TREE){
gold += 800; buffDark = true;
}else gold += earn;
l.seed = false; l.full = false; l.grow = 0; l.harvested = false;
break;
}
}
}
})
}
function drawServants(){
if(gameVer <8) return;
servants.forEach(s=>{
drawPixelRect(s.x+4,s.y,20,20,PALETTE.servant);
drawPixelRect(s.x+6,s.y+20,16,12,"#774422");
drawPixelRect(s.x+8,s.y+6,4,4,"#000");
drawPixelRect(s.x+16,s.y+6,4,4,"#000");
})
document.getElementById('servantCount').innerText = servants.length;
}
// ========== 地图切换 ==========
function goHell(){
if(!hellOpen){alert("切换V3及以上解锁地狱");return;}
if(level < 3){alert(`LV${level}不足LV3,还差${getLevelNeed()-gold}金币升级`);return;}
isHellMap = true; isHeavenMap = false; bandits = [];
}
function goHeaven(){
if(!heavenOpen){alert("仅V6/V7/V8/V9解锁天堂");return;}
if(level < 5){alert(`当前LV${level},天堂需要LV5`);return;}
isHeavenMap = true; isHellMap = false; bandits = [];
heavenSeedPick = {x:680,y:330,w:24,h:24};
}
function backOriginWorld(){
isHellMap = false;
isHeavenMap = false;
bandits = [];
alert("已返回主世界");
}
// ========== 天堂特效 ==========
function spawnHeavenParticle(){
if(gamePause) return;
if(!isHeavenMap || gameVer <6) return;
if(tick % 8 === 0){
heavenParticles.push({x: Math.random()*800, y:340, vy:-1-Math.random()*2, life:80})
}
}
function drawHeavenParticles(){
heavenParticles.forEach((p,i)=>{
p.y += p.vy; p.life--;
drawPixelRect(p.x,p.y,3,3,"#ffffff");
if(p.life <=0) heavenParticles.splice(i,1);
})
}
function drawHeavenSeedPick(){
if(!heavenSeedPick || !isHeavenMap) return;
let s = heavenSeedPick;
drawPixelRect(s.x,s.y,s.w,s.h,"#fffde0");
drawPixelRect(s.x+6,s.y+6,12,12,"#ffffff");
}
// ========== 弹窗控制 ==========
function closeAllPopup(){
document.getElementById('mask').style.display = "none";
document.getElementById('shopBox').style.display = "none";
document.getElementById('settingBox').style.display = "none";
document.getElementById('houseBox').style.display = "none";
gamePause = false;
}
function openHouse(){
document.getElementById('mask').style.display = "block";
document.getElementById('houseBox').style.display = "block";
gamePause = true;
}
function closeHouse(){
closeAllPopup();
}
function eatMeal(){
buffEat = true;
buffEatTick = 1200;
alert("吃饱饭啦!短时间作物生长小幅加速");
closeAllPopup();
}
function sleepNight(){
dayCycleTick = 0;
dayPhase = "day";
alert("一觉睡到天亮,昼夜重置为白天");
closeAllPopup();
}
// ========== 昼夜系统 ==========
function updateDayCycle(){
if(gamePause) return;
dayCycleTick++;
let ratio = dayCycleTick / DAY_CYCLE_LEN;
if(ratio < 0.35){
dayPhase = "day";
if(!mealFlagMorning){
mealFlagMorning = true;
alert("【早餐时间】必须进屋吃饭,无法跳过!点击农场小屋用餐");
}
}else if(ratio < 0.65){
dayPhase = "dusk";
if(!mealFlagNoon){
mealFlagNoon = true;
alert("【午餐时间】强制用餐,前往小屋吃饭");
}
}else{
dayPhase = "night";
if(!mealFlagDinner){
mealFlagDinner = true;
alert("【晚餐时间】必须吃饭,不能拒绝");
}
if(!mealFlagMidnight){
mealFlagMidnight = true;
let ok = confirm("【夜宵】是否吃夜宵?可选择拒绝");
if(ok){
buffEat = true; buffEatTick = 800;
}
}
}
document.getElementById('dayPhase').innerText = dayPhase==="day"?"白天":dayPhase==="dusk"?"黄昏":"夜晚";
}
// ========== 存档系统 ==========
function saveSlot(num){
const saveData = {
gameVer,gold,level,landMax,landList,player,
hellOpen,heavenOpen,isHellMap,isHeavenMap,bandits,
hasWeapon,hasMachine,tick,pets,servants,
netherSeed,lifeTreeSeed,buffAngel,buffDark,buffEat,buffEatTick,
heavenSeedPick,heavenParticles,dayCycleTick,dayPhase,
mealFlagMorning,mealFlagNoon,mealFlagDinner,mealFlagMidnight,MAX_BANDIT,
autoLevelSwitch
};
localStorage.setItem("farmSave"+num, JSON.stringify(saveData));
alert("✅ 存档"+num+"保存成功");
}
function loadSlot(num){
const saveStr = localStorage.getItem("farmSave"+num);
if(!saveStr){
alert("❌ 存档"+num+"为空,无记录");
return;
}
try{
const d = JSON.parse(saveStr);
gameVer = d.gameVer;
gold = d.gold;
level = d.level;
landMax = d.landMax;
landList = d.landList;
player = d.player;
hellOpen = d.hellOpen;
heavenOpen = d.heavenOpen;
isHellMap = d.isHellMap;
isHeavenMap = d.isHeavenMap;
bandits = d.bandits;
hasWeapon = d.hasWeapon;
hasMachine = d.hasMachine;
tick = d.tick;
pets = d.pets;
servants = d.servants;
netherSeed = d.netherSeed;
lifeTreeSeed = d.lifeTreeSeed;
buffAngel = d.buffAngel;
buffDark = d.buffDark;
buffEat = d.buffEat;
buffEatTick = d.buffEatTick;
heavenSeedPick = d.heavenSeedPick;
heavenParticles = d.heavenParticles;
dayCycleTick = d.dayCycleTick;
dayPhase = d.dayPhase;
mealFlagMorning = d.mealFlagMorning;
mealFlagNoon = d.mealFlagNoon;
mealFlagDinner = d.mealFlagDinner;
mealFlagMidnight = d.mealFlagMidnight;
autoLevelSwitch = d.autoLevelSwitch ?? false;
const btn = document.getElementById("autoLvBtn");
if(autoLevelSwitch){
btn.innerText = "自动升级:开启";
btn.style.background = "#22dd22";
}else{
btn.innerText = "自动升级:关闭";
btn.style.background = "#ff7722";
}
alert("✅ 存档"+num+"读取完成");
renderShop();
}catch(e){
alert("❌ 存档"+num+"损坏");
console.error(e);
}
}
// ========== 主游戏循环 ==========
function gameLoop(){
tick++;
// 背景
let skyTop,skyBottom;
if(isHeavenMap){skyTop=PALETTE.heavenSky;skyBottom=PALETTE.heavenSkyGrad;}
else if(isHellMap){skyTop=PALETTE.hellSky;skyBottom=PALETTE.hellSkyGradient;}
else {
if(dayPhase==="day"){skyTop=PALETTE.skyDay;skyBottom=PALETTE.skyDayGrad;}
else if(dayPhase==="dusk"){skyTop=PALETTE.skyDusk;skyBottom=PALETTE.skyDuskGrad;}
else {skyTop=PALETTE.skyNight;skyBottom=PALETTE.skyNightGrad;}
}
ctx.fillStyle=skyTop;ctx.fillRect(0,0,800,500);
if(!isHellMap && !isHeavenMap && dayPhase==="day"){drawCloud(120,60);drawCloud(350,90);drawCloud(600,50);}
// 生长速度
let growSpeed = 0.03;
if(hasMachine && !isHellMap && !isHeavenMap) growSpeed *= 2;
if(buffAngel) growSpeed *= 3;
if(buffDark && isHellMap) growSpeed *= 8;
if(buffEat) {growSpeed *= 1.4; buffEatTick--; if(buffEatTick <=0) buffEat = false;}
// 作物生长
if(!gamePause){
landList.forEach(l=>{
if(l.seed && !l.full){
l.grow += growSpeed;
if(l.grow >=7) l.full = true;
}
})
}
// 自动升级逻辑
if(autoLevelSwitch && !gamePause){
const cost = getLevelNeed();
if(gold >= cost){
gold -= cost;
level += 1;
}
}
// 游戏逻辑
spawnBandit();
banditStealLogic();
petAttackBandit();
servantAutoHarvest();
spawnHeavenParticle();
updateDayCycle();
// 渲染
drawLand();
drawHouse();
drawHeavenParticles();
drawHeavenSeedPick();
drawFarmer();
drawBandits();
drawPets();
drawServants();
// UI更新
document.getElementById('lv').innerText = level;
document.getElementById('gold').innerText = gold;
document.getElementById('landNum').innerText = landMax;
document.getElementById('lvNeed').innerText = getLevelNeed();
document.getElementById('seedNether').innerText = netherSeed;
document.getElementById('seedLife').innerText = lifeTreeSeed;
document.getElementById('buffAngel').innerText = buffAngel?"激活":"无";
document.getElementById('buffDark').innerText = buffDark?"激活":"无";
requestAnimationFrame(gameLoop);
}
// ========== 点击交互 ==========
document.getElementById('gameCanvas').onclick = e=>{
if(gamePause) return;
const rect = e.target.getBoundingClientRect();
const mx = e.clientX - rect.left;
const my = e.clientY - rect.top;
// 小屋
if(gameVer >=8){
let h = housePos;
if(mx >= h.x && mx <= h.x+h.w && my >= h.y && my <= h.y+h.h){
openHouse();
return;
}
}
// 天堂种子拾取
if(gameVer >=6 && isHeavenMap && heavenSeedPick){
let s = heavenSeedPick;
if(mx>s.x && mx<s.x+s.w && my>s.y && my<s.y+s.h){
lifeTreeSeed +=1;
heavenSeedPick = null;
alert("拾取生命树种子!Win7/8种下100%成活");
}
}
// 攻击盗贼
if(gameVer >=4){
for(let i=bandits.length-1;i>=0;i--){
const b = bandits[i];
if(mx>b.x && mx <b.x+b.w && my>b.y && my <b.y+b.h){
if(!hasWeapon){alert("商店购买铁剑才能攻击盗贼");return;}
b.hp--;
if(b.hp <=0){
bandits.splice(i,1);
gold += 100;
}
return;
}
}
}
// 田地播种/收割
landList.forEach(land=>{
if(mx>land.x && mx <land.x+land.w && my>land.y && my <land.y+land.h){
if(!land.seed && !land.stolen){
// 特殊种子播种
if(isHellMap && netherSeed > 0){
netherSeed--;
land.seed = true; land.grow = 0;
land.isHellCrop = true;
land.cropType = CROP_TYPE.NETHER_TREE;
return;
}
if(isHeavenMap && lifeTreeSeed > 0){
lifeTreeSeed--;
land.seed = true; land.grow = 0;
land.isHellCrop = false;
land.cropType = CROP_TYPE.LIFE_TREE;
return;
}
// 普通播种
land.seed = true; land.grow = 0;
land.isHellCrop = isHellMap;
if(gameVer >=5 && isHellMap && Math.random() < NETHER_SPAWN_CHANCE){
land.cropType = Math.random()>0.5 ? CROP_TYPE.NETHER_FLOWER : CROP_TYPE.NETHER_TREE;
}else if(gameVer >=5 && !isHellMap && !isHeavenMap){
let r = Math.random();
if(r<0.35) land.cropType=CROP_TYPE.WHEAT;
else if(r<0.55) land.cropType=CROP_TYPE.FRUIT_TREE;
else if(r<0.78) land.cropType=CROP_TYPE.WILD_GRASS;
else land.cropType=CROP_TYPE.WILD_FLOWER;
}else if(gameVer >=6 && isHeavenMap){
land.cropType = Math.random()>0.7 ? CROP_TYPE.WILD_FLOWER : CROP_TYPE.WHEAT;
}else land.cropType=CROP_TYPE.WHEAT;
}else if(land.full && !land.stolen){
// 收割仅加金币,不再自动升级
let earn = land.isHellCrop ? 400 : 200;
if(land.cropType === CROP_TYPE.LIFE_TREE){
gold += 1000; buffAngel = true;
}else if(land.cropType === CROP_TYPE.NETHER_TREE){
let opt = confirm("冥界果实:吃掉获得黑暗之力|取消留存种子");
if(opt){buffDark = true;gold += 800;alert("黑暗之力:地狱作物×8生长");}
else{netherSeed +=1;alert(`冥界种子+1`);}
}else{
gold += earn;
}
land.seed = false; land.full = false; land.grow = 0;
}
}
})
}
// ========== 商店系统 ==========
function openShop(){
document.getElementById('mask').style.display = "block";
document.getElementById('shopBox').style.display = "block";
gamePause = true;
renderShop();
}
function closeShop(){
closeAllPopup();
}
function openSetting(){
document.getElementById('mask').style.display = "block";
document.getElementById('settingBox').style.display = "block";
gamePause = true;
}
function closeSetting(){
closeAllPopup();
}
function renderShop(){
const list = document.getElementById('shopList');
list.innerHTML = "";
const goods = [];
goods.push({name:"扩大田地一块",cost:600,func:()=>{landMax++;initLand()}});
goods.push({name:"石锄头",cost:300,func:()=>{}});
if(gameVer >=2) goods.push({name:"自动灌溉机器",cost:1500,func:()=>{hasMachine=true}});
if(gameVer >=4) goods.push({name:"像素铁剑防盗贼",cost:2200,func:()=>{hasWeapon=true}});
if(gameVer >=3){
goods.push({name:"灰狼 30金币",cost:30,func:()=>createPet(PET_TYPE.WOLF)});
goods.push({name:"哈士奇(地狱瞬杀盗贼) 120",cost:120,func:()=>createPet(PET_TYPE.HUSKY)});
goods.push({name:"猫咪 40",cost:40,func:()=>createPet(PET_TYPE.CAT)});
goods.push({name:"肉猪 25",cost:25,func:()=>createPet(PET_TYPE.PIG)});
goods.push({name:"奶牛 35",cost:35,func:()=>createPet(PET_TYPE.COW)});
goods.push({name:"绵羊 20",cost:20,func:()=>createPet(PET_TYPE.SHEEP)});
}
if(gameVer >=5) goods.push({name:"冥界种子",cost:800,func:()=>{netherSeed+=1;renderShop();}});
if(gameVer >=6) goods.push({name:"备用生命树种子",cost:3000,func:()=>{lifeTreeSeed+=1;renderShop();}});
if(gameVer === 8 || gameVer ===9) goods.push({name:"佣人(每秒自动收1块作物) 200金币",cost:200,func:()=>{createServant();renderShop();}});
goods.forEach(item=>{
let div = document.createElement("div");
div.className = "shop-item";
div.innerHTML = `<span>${item.name}</span><span>${item.cost}金币</span>`;
let buyBtn = document.createElement("button");
buyBtn.className = "btn";
buyBtn.innerText = "购买";
buyBtn.onclick = ()=>{
if(gold >= item.cost){gold -= item.cost;item.func();renderShop();}
else alert("金币不足,多种地赚钱");
}
div.appendChild(buyBtn);
list.appendChild(div);
})
}
// 启动游戏
initLand();
loadSlot(1);
gameLoop();
</script>
</body>
</html>Game Source: 像素农夫物语 V9 手动自动等级升级完整版
Creator: BraveDragon92
Libraries: none
Complexity: complex (995 lines, 43.7 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: v9-bravedragon92" to link back to the original. Then publish at arcadelab.ai/publish.