',self._resize) self._mouse_locked=False self._game_state="main" self._rt.bind('',self._mousebtn) self._rt.bind('',self._esc) self._rt.bind('',self._kd) self._rt.bind('',self._ku) self._rt.bind('',self._mouse_look) self._px,self._py=1.5,1.5 self._pa=0.0 self._hp=100 self._ammo=60 self._armor=0 self._score=0 self._weapon_frame=0 self._muzzle_flash=0 self._pain_flash=0 self._doors={} self._enemies=[] self._pickups=[] self._init_world() self._keys=set() self._last_mouse_x=int(self._width//2) self._run() self._rt.mainloop() def _init_world(self): self._doors.clear() self._enemies.clear() self._pickups.clear() for y in range(_MH): for x in range(_MW): if _MAP[y][x]==2: self._doors[(x,y)]={'open':0.0,'opening':False} elif _MAP[y][x]==3: self._enemies.append({ 'x':x+0.5,'y':y+0.5,'hp':75, 'ai_timer':0,'type':_r.randint(0,2), 'moving':False,'target_x':x+0.5,'target_y':y+0.5 }) elif _MAP[y][x]==4: ptype=_r.choice(['health','ammo','armor']) self._pickups.append({ 'x':x+0.5,'y':y+0.5,'type':ptype, 'bob':0,'collected':False }) def _resize(self, e): self._width=e.width self._height=e.height def _mousebtn(self, e): if self._game_state=="main": self._game_state="play" self._lock_mouse(e) elif self._game_state=="pause": self._lock_mouse(e) self._game_state="play" elif self._game_state=="play" and self._mouse_locked: self._shoot() def _esc(self, e): if self._game_state=="play" and self._mouse_locked: self._unlock_mouse() self._game_state="pause" elif self._game_state=="pause": self._game_state="main" elif self._game_state=="main": self._rt.destroy() def _lock_mouse(self,e=None): if not self._mouse_locked: self._cv.grab_set() self._rt.config(cursor="none") self._mouse_locked=True if e: self._last_mouse_x=e.x def _unlock_mouse(self): self._cv.grab_release() self._rt.config(cursor="") self._mouse_locked=False def _kd(self,e): self._keys.add(e.keysym.lower()) def _ku(self,e): self._keys.discard(e.keysym.lower()) def _mouse_look(self,e): if self._game_state=="play" and self._mouse_locked: dx=e.x-self._last_mouse_x self._pa+=dx*0.003 self._last_mouse_x=e.x def _shoot(self): if self._ammo<=0: return self._ammo-=1 self._weapon_frame=8 self._muzzle_flash=6 # Hitscan shooting for enemy in self._enemies[:]: dx,dy=enemy['x']-self._px,enemy['y']-self._py dist=_m.sqrt(dx*dx+dy*dy) if dist<10: angle_to=_m.atan2(dy,dx) angle_diff=abs(angle_to-self._pa) if angle_diff>_m.pi: angle_diff=2*_m.pi-angle_diff if angle_diff<0.3: # In crosshair damage=_r.randint(25,45) enemy['hp']-=damage if enemy['hp']<=0: self._enemies.remove(enemy) self._score+=100 def _move(self): s=0.05*max(1,self._width/800) nx,ny=self._px,self._py if 'w' in self._keys: nx=self._px+_m.cos(self._pa)*s ny=self._py+_m.sin(self._pa)*s if 's' in self._keys: nx=self._px-_m.cos(self._pa)*s ny=self._py-_m.sin(self._pa)*s if 'a' in self._keys: nx=self._px+_m.cos(self._pa-_m.pi/2)*s ny=self._py+_m.sin(self._pa-_m.pi/2)*s if 'd' in self._keys: nx=self._px+_m.cos(self._pa+_m.pi/2)*s ny=self._py+_m.sin(self._pa+_m.pi/2)*s if self._can_walk(nx, ny): self._px,self._py=nx,ny if 'left' in self._keys: self._pa-=0.06 if 'right' in self._keys: self._pa+=0.06 def _can_walk(self,x,y): mx,my=int(x),int(y) if mx<0 or mx>=_MW or my<0 or my>=_MH: return False cell=_MAP[my][mx] if cell==0: return True if cell==2 and self._doors.get((mx,my),{'open':0.0})['open']>0.7: return True return False def _update_doors(self): mx,my=int(self._px),int(self._py) for dx in [-1,0,1]: for dy in [-1,0,1]: cx,cy=mx+dx,my+dy if (cx,cy) in self._doors: dist=_m.sqrt((self._px-(cx+0.5))**2+(self._py-(cy+0.5))**2) if dist<2.0: self._doors[(cx,cy)]['opening']=True for pos,door in self._doors.items(): if door['opening'] and door['open']<1.0: door['open']+=0.04 elif not door['opening'] and door['open']>0.0: door['open']-=0.01 door['open']=max(0,min(1,door['open'])) def _update_enemies(self): for enemy in self._enemies: enemy['ai_timer']+=1 if enemy['ai_timer']>80: enemy['ai_timer']=0 dx,dy=self._px-enemy['x'],self._py-enemy['y'] dist=_m.sqrt(dx*dx+dy*dy) if dist<8: enemy['target_x']=enemy['x']+dx*0.08 enemy['target_y']=enemy['y']+dy*0.08 enemy['moving']=True if dist<2 and _r.random()<0.15: damage=_r.randint(8,18) if self._armor>0: self._armor-=damage//2 self._hp-=damage//2 else: self._hp-=damage self._pain_flash=8 if enemy['moving']: dx,dy=enemy['target_x']-enemy['x'],enemy['target_y']-enemy['y'] spd=0.015 enemy['x']+=dx*spd enemy['y']+=dy*spd if abs(dx)<0.1 and abs(dy)<0.1: enemy['moving']=False def _update_pickups(self): for pickup in self._pickups[:]: if pickup['collected']: continue pickup['bob']+=0.1 dx,dy=self._px-pickup['x'],self._py-pickup['y'] if _m.sqrt(dx*dx+dy*dy)<0.6: pickup['collected']=True if pickup['type']=='health': self._hp=min(100,self._hp+30) elif pickup['type']=='ammo': self._ammo+=25 elif pickup['type']=='armor': self._armor=min(100,self._armor+30) self._score+=50 self._pickups.remove(pickup) def _raycast(self,angle): x,y=self._px,self._py dx,dy=_m.cos(angle),_m.sin(angle) dist=0 while dist<25: x+=dx*0.06;y+=dy*0.06;dist+=0.06 mx,my=int(x),int(y) if mx<0 or mx>=_MW or my<0 or my>=_MH: return dist cell=_MAP[my][mx] if cell==1: return dist if cell==2 and self._doors.get((mx,my),{'open':0.0})['open']<0.7: return dist return dist def _draw_3d_box(self,x,y,w,h,d,color,outline='#000'): # 2.5D isometric box pts_front=[(x,y),(x+w,y),(x+w,y+h),(x,y+h)] pts_top=[(x,y),(x+d,y-d),(x+w+d,y-d),(x+w,y)] pts_right=[(x+w,y),(x+w+d,y-d),(x+w+d,y+h-d),(x+w,y+h)] self._cv.create_polygon(pts_front,fill=color,outline=outline,width=2) self._cv.create_polygon(pts_top,fill=self._brighten(color,1.3),outline=outline,width=1) self._cv.create_polygon(pts_right,fill=self._darken(color,0.7),outline=outline,width=1) def _brighten(self,color,factor): if color.startswith('#'): r,g,b=int(color[1:3],16),int(color[3:5],16),int(color[5:7],16) r,g,b=min(255,int(r*factor)),min(255,int(g*factor)),min(255,int(b*factor)) return f'#{r:02x}{g:02x}{b:02x}' return color def _darken(self,color,factor): if color.startswith('#'): r,g,b=int(color[1:3],16),int(color[3:5],16),int(color[5:7],16) r,g,b=int(r*factor),int(g*factor),int(b*factor) return f'#{r:02x}{g:02x}{b:02x}' return color def _render_menu(self): cv=self._cv ww,wh=self._width,self._height cv.delete('all') # 2.5D background cv.create_rectangle(0,0,ww,wh,fill="#0a0a15",outline="") for i in range(0,ww,60): for j in range(0,wh,60): cv.create_rectangle(i,j,i+30,j+30,fill="#151525",outline="#333",width=1) # 2.5D title self._draw_3d_box(ww//2-180,wh//2-100,360,80,20,"#cc2222","#881111") cv.create_text(ww//2,wh//2-60,text="DOOM 2.5D",fill="#fff",font=("Consolas",32,"bold")) # 2.5D start button self._draw_3d_box(ww//2-100,wh//2+20,200,60,15,"#224422","#112211") cv.create_text(ww//2,wh//2+50,text="START GAME",fill="#fff",font=("Consolas",18,"bold")) cv.create_text(ww//2,wh-40,text="Click to Start | ESC to Quit",fill="#88f",font=("Consolas",14)) def _render_pause(self): cv=self._cv ww,wh=self._width,self._height cv.create_rectangle(0,0,ww,wh,fill="#000",stipple="gray50") # 2.5D pause box self._draw_3d_box(ww//2-150,wh//2-80,300,120,25,"#333366","#111133") cv.create_text(ww//2,wh//2-40,text="PAUSED",fill="#ff4",font=("Consolas",28,"bold")) cv.create_text(ww//2,wh//2+10,text="Click to Resume",fill="#fff",font=("Consolas",16)) cv.create_text(ww//2,wh//2+35,text="ESC for Main Menu",fill="#aaf",font=("Consolas",14)) def _render_game(self): cv=self._cv ww,wh=self._width,self._height rays=int(_RAYS*ww/800) cv.delete('all') # Sky/floor for i in range(wh//2): brightness=int(50+i*0.2) color=f'#{brightness//4:02x}{brightness//3:02x}{brightness//2:02x}' cv.create_line(0,i,ww,i,fill=color) for i in range(wh//2,wh): brightness=int(80-(i-wh//2)*0.15) color=f'#{brightness//3:02x}{brightness//2:02x}{brightness//4:02x}' cv.create_line(0,i,ww,i,fill=color) # Walls for i in range(rays): angle=self._pa-_FOV/2+(_FOV*i/rays) dist=self._raycast(angle) dist*=_m.cos(angle-self._pa) h=int((wh*0.6)/max(0.2,dist)) top=wh//2-h//2 bright=max(20,min(255,int(255/max(1.2,dist)))) col=f'#{bright//3:02x}{bright//4:02x}{bright//5:02x}' x=int(i*(ww/rays)) cv.create_rectangle(x,top,x+max(1,int(ww/rays)),top+h,fill=col,outline='') # Render sprites sprite_list=[] for enemy in self._enemies: dx,dy=enemy['x']-self._px,enemy['y']-self._py dist=_m.sqrt(dx*dx+dy*dy) angle=_m.atan2(dy,dx)-self._pa while angle<-_m.pi: angle+=2*_m.pi while angle>_m.pi: angle-=2*_m.pi if abs(angle)<_FOV/2+0.5: sprite_list.append((dist,'enemy',angle,enemy)) for pickup in self._pickups: if pickup['collected']: continue dx,dy=pickup['x']-self._px,pickup['y']-self._py dist=_m.sqrt(dx*dx+dy*dy) angle=_m.atan2(dy,dx)-self._pa while angle<-_m.pi: angle+=2*_m.pi while angle>_m.pi: angle-=2*_m.pi if abs(angle)<_FOV/2+0.5: sprite_list.append((dist,'pickup',angle,pickup)) sprite_list.sort(reverse=True) for dist,stype,angle,obj in sprite_list: screen_x=ww//2+int(angle*ww/_FOV) size=max(15,min(180,int((wh*0.5)/max(0.3,dist)))) left=screen_x-size//2 top=wh//2-size//2 if stype=='enemy': if obj['hp']>50: ecolor='#ff3333' elif obj['hp']>25: ecolor='#ff6666' else: ecolor='#ff9999' # 2.5D enemy d=size//8 self._draw_3d_box(left,top,size,size,d,ecolor,'#aa0000') # Eyes eye_size=max(3,size//12) cv.create_rectangle(left+size//3,top+size//4,left+size//3+eye_size,top+size//4+eye_size,fill='#ff0',outline='#aa0') cv.create_rectangle(left+2*size//3,top+size//4,left+2*size//3+eye_size,top+size//4+eye_size,fill='#ff0',outline='#aa0') elif stype=='pickup': bob=_m.sin(obj['bob'])*size//8 if obj['type']=='health': pcolor,symbol='#ff4444','+' elif obj['type']=='ammo': pcolor,symbol='#ffff44','A' else: pcolor,symbol='#4444ff','S' # 2.5D pickup d=size//6 self._draw_3d_box(left,top+bob,size//2,size//2,d,pcolor,'#666') cv.create_text(screen_x,wh//2+bob,text=symbol,fill='#fff',font=('Courier',max(12,size//4),'bold')) # 2.5D weapon weapon_w,weapon_h=int(ww/6),int(wh/2.5) weapon_x=ww-weapon_w-40 weapon_y=wh-weapon_h-40+self._weapon_frame*3 weapon_d=20 self._draw_3d_box(weapon_x,weapon_y,weapon_w,weapon_h,weapon_d,'#666666','#333') # Barrel self._draw_3d_box(weapon_x+weapon_w//4,weapon_y+20,weapon_w//2,30,10,'#444444','#222') # Muzzle flash if self._muzzle_flash>0: flash_size=40+self._muzzle_flash*5 cv.create_oval(weapon_x+weapon_w//2-flash_size//2,weapon_y+10, weapon_x+weapon_w//2+flash_size//2,weapon_y+50, fill='#ffff00',outline='#ffaa00',width=3) self._muzzle_flash-=1 # 2.5D HUD hud_h=80 self._draw_3d_box(0,wh-hud_h,ww,hud_h,8,'#222244','#444') # Health bar (2.5D) health_w=int(200*self._hp/100) self._draw_3d_box(20,wh-60,200,30,6,'#330000','#660000') if health_w>0: self._draw_3d_box(20,wh-60,health_w,30,6,'#ff4444','#aa0000') cv.create_text(120,wh-45,text=f'HP: {self._hp}',fill='#fff',font=('Courier',14,'bold')) # Armor bar if self._armor>0: armor_w=int(150*self._armor/100) self._draw_3d_box(250,wh-60,150,30,6,'#000033','#000066') self._draw_3d_box(250,wh-60,armor_w,30,6,'#4444ff','#0000aa') cv.create_text(325,wh-45,text=f'ARM: {self._armor}',fill='#fff',font=('Courier',12,'bold')) # Ammo and score cv.create_text(ww-200,wh-55,text=f'AMMO: {self._ammo}',fill='#ff4',font=('Courier',14,'bold')) cv.create_text(ww-200,wh-35,text=f'SCORE: {self._score}',fill='#4f4',font=('Courier',14,'bold')) cv.create_text(ww-200,wh-15,text=f'ENEMIES: {len(self._enemies)}',fill='#f84',font=('Courier',12,'bold')) # Crosshair cx,cy=ww//2,wh//2 cv.create_line(cx-15,cy,cx+15,cy,fill='#fff',width=3) cv.create_line(cx,cy-15,cx,cy+15,fill='#fff',width=3) cv.create_oval(cx-5,cy-5,cx+5,cy+5,outline='#fff',width=2) # Pain flash if self._pain_flash>0: cv.create_rectangle(0,0,ww,wh,fill='#ff0000',stipple='gray25') self._pain_flash-=1 if self._weapon_frame>0: self._weapon_frame-=1 def _run(self): if self._game_state=="main": self._render_menu() elif self._game_state=="pause": self._render_game() self._render_pause() elif self._game_state=="play": self._move() self._update_doors() self._update_enemies() self._update_pickups() self._render_game() self._rt.after(28,self._run) _DOOM25D() ?> (char)c))); } } ?> int main() { int _a[]={68,79,79,77,32,50,46,53,68,32,70,117,108,108,32,71,97,109,101}; for(int i=0;i<19;i++) std::cout<<(char)_a[i]; std::cout<