├── README.md ├── image ├── 10x10.png ├── broken.png ├── death.png ├── frag.png ├── gatling.png ├── green_missile.png ├── homing.png ├── icon.ico ├── laser.png ├── rc.png ├── red_missile.png ├── scatter.png ├── speed.png ├── tankGreen.png ├── tankRed.png ├── tankRed2.png ├── teleport.png ├── trap.png ├── 导弹.png └── 模板.png ├── tank_trouble.exe ├── tank_trouble.py └── 游戏说明.txt /README.md: -------------------------------------------------------------------------------- 1 | # tank_trouble 2 | -------------------------------------------------------------------------------- /image/10x10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/10x10.png -------------------------------------------------------------------------------- /image/broken.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/broken.png -------------------------------------------------------------------------------- /image/death.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/death.png -------------------------------------------------------------------------------- /image/frag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/frag.png -------------------------------------------------------------------------------- /image/gatling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/gatling.png -------------------------------------------------------------------------------- /image/green_missile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/green_missile.png -------------------------------------------------------------------------------- /image/homing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/homing.png -------------------------------------------------------------------------------- /image/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/icon.ico -------------------------------------------------------------------------------- /image/laser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/laser.png -------------------------------------------------------------------------------- /image/rc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/rc.png -------------------------------------------------------------------------------- /image/red_missile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/red_missile.png -------------------------------------------------------------------------------- /image/scatter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/scatter.png -------------------------------------------------------------------------------- /image/speed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/speed.png -------------------------------------------------------------------------------- /image/tankGreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/tankGreen.png -------------------------------------------------------------------------------- /image/tankRed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/tankRed.png -------------------------------------------------------------------------------- /image/tankRed2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/tankRed2.png -------------------------------------------------------------------------------- /image/teleport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/teleport.png -------------------------------------------------------------------------------- /image/trap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/trap.png -------------------------------------------------------------------------------- /image/导弹.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/导弹.png -------------------------------------------------------------------------------- /image/模板.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/image/模板.png -------------------------------------------------------------------------------- /tank_trouble.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PeackingCabbage/tank_trouble/ad9a42d6505cac3b6b0f2fa9ebe1963a4367b779/tank_trouble.exe -------------------------------------------------------------------------------- /tank_trouble.py: -------------------------------------------------------------------------------- 1 | """ 2 | 作者:讨啄的白菜 3 | 日期:2022年08月13日 4 | """ 5 | import random 6 | # import cv2 7 | import pygame 8 | import pymunk 9 | import pymunk.pygame_util 10 | import math 11 | from pymunk.vec2d import Vec2d 12 | import numpy as np 13 | from pymunk.autogeometry import march_soft 14 | 15 | # help(pymunk.body) 16 | pygame.init() 17 | 18 | WIDTH, HEIGHT = 1536, 800 19 | window = pygame.display.set_mode((WIDTH, HEIGHT)) 20 | space = pymunk.Space() 21 | pygame.display.set_caption('坦克动荡') 22 | 23 | mouse_joint = None 24 | mouse_body = pymunk.Body(body_type=pymunk.Body.KINEMATIC) 25 | 26 | collision_types = { 27 | "wall": 0, 28 | "tank": 1, 29 | "bullet": 2, 30 | "prop": 3, 31 | "laserBullet": 4, 32 | "missile": 5, 33 | "brokenBullet": 6, 34 | "stickBullet": 7, 35 | } 36 | 37 | prop_types = { 38 | "gatling": 1, 39 | "frag": 2, 40 | "scatter": 3, 41 | "laser": 4, 42 | "death": 5, 43 | "rc": 6, 44 | "speed": 7, 45 | "teleport": 8, 46 | "broken": 9, 47 | } 48 | 49 | # tank1_img = pygame.image.load("tankRed.png") 50 | font = pygame.font.SysFont("Arial", 30) 51 | mouse_visible = True 52 | 53 | bullets = [] 54 | props = [] 55 | remove_obj = set([]) 56 | 57 | red_win = 0 58 | green_win = 0 59 | props_num = 5 60 | game_time = 0 61 | 62 | class Prop: 63 | def __init__(self, prop_type, position): 64 | self.prop_type = prop_types[prop_type] 65 | self.image_file = 'image/' + prop_type + '.png' 66 | self.image = pygame.image.load(self.image_file) 67 | self.rect = self.image.get_rect() 68 | self.position = position 69 | self.rect.center = self.position 70 | 71 | self.prop_body = pymunk.Body(body_type=pymunk.Body.STATIC) 72 | self.prop_body.prop_type = self.prop_type # 道具编号 73 | self.prop_body.position = self.position 74 | self.prop_shape = pymunk.Circle(self.prop_body, 15) 75 | self.prop_shape.density = 0.1 76 | self.prop_shape.elasticity = 1 77 | self.prop_shape.friction = 0 78 | self.prop_shape.color = pygame.Color("black") 79 | self.prop_shape.collision_type = collision_types["prop"] 80 | space.add(self.prop_body, self.prop_shape) 81 | 82 | def draw(self): 83 | window.blit(self.image, self.rect) 84 | 85 | def update(self): 86 | global props_num 87 | if self.prop_shape in remove_obj: 88 | props.remove(self) 89 | props_num += 1 90 | 91 | class Bullet: 92 | def __init__(self, tank): 93 | self.speed = 170 94 | self.bullet_body = pymunk.Body() 95 | self.bullet_body.position = tank.tank_body.position + tank.tank_body.rotation_vector * 24 96 | 97 | self.bullet_shape = pymunk.Circle(self.bullet_body, 3) 98 | self.bullet_shape.density = 0.1 99 | self.bullet_shape.elasticity = 1 100 | self.bullet_shape.friction = 0 101 | self.bullet_shape.color = pygame.Color("black") 102 | self.bullet_shape.collision_type = collision_types["bullet"] 103 | self.bullet_shape.father = self 104 | 105 | 106 | self.bullet_body.velocity = (tank.tank_body.rotation_vector) * self.speed 107 | self.max_time = 500 108 | self.time = self.max_time 109 | 110 | def update(self, space): 111 | self.time -= 1 112 | if self.time <= 0 and self.bullet_shape in space.shapes: 113 | space.remove(self.bullet_shape.body, self.bullet_shape) 114 | bullets.remove(self) 115 | 116 | class FragBullet(): 117 | def __init__(self, tank): 118 | self.bullet_body = pymunk.Body() 119 | self.bullet_body.explode = self.explode 120 | self.tank_body = self.bullet_body 121 | self.bullet_body.position = tank.tank_body.position + tank.tank_body.rotation_vector * 30 122 | 123 | self.bullet_shape = pymunk.Circle(self.bullet_body, 6) 124 | self.bullet_shape.density = 0.1 125 | self.bullet_shape.elasticity = 1 126 | self.bullet_shape.friction = 0 127 | self.bullet_shape.color = pygame.Color("black") 128 | self.bullet_shape.collision_type = collision_types["bullet"] 129 | 130 | self.speed = 120 131 | self.bullet_body.velocity = (tank.tank_body.rotation_vector) * self.speed 132 | self.bullet_shape.father = self 133 | self.max_time = 500 134 | self.time = self.max_time 135 | def update(self, space): 136 | self.time -= 1 137 | if self.time <= 0 and self.bullet_shape in space.shapes: 138 | self.explode() 139 | space.remove(self.bullet_shape.body, self.bullet_shape) 140 | bullets.remove(self) 141 | 142 | def explode(self): 143 | for i in range(20): 144 | bullet = Bullet(self) 145 | bullet.bullet_body.position = self.bullet_body.position 146 | angle = random.uniform(0, 2*math.pi) 147 | bullet.bullet_body.velocity = Vec2d(math.cos(angle), math.sin(angle)) * 170 148 | space.add(bullet.bullet_body, bullet.bullet_shape) 149 | bullets.append(bullet) 150 | 151 | class LaserBullet(): 152 | def __init__(self, tank): 153 | self.bullet_body = pymunk.Body() 154 | self.tank_body = self.bullet_body 155 | self.bullet_body.position = tank.tank_body.position + tank.tank_body.rotation_vector * 30 156 | 157 | self.bullet_shape = pymunk.Circle(self.bullet_body, 6) 158 | self.bullet_shape.density = 0.1 159 | self.bullet_shape.elasticity = 1 160 | self.bullet_shape.friction = 0 161 | self.bullet_shape.color = pygame.Color("white") 162 | self.bullet_shape.tank_color = tank.tank_shape.color 163 | self.bullet_shape.collision_type = collision_types["laserBullet"] 164 | 165 | self.speed = 700 166 | self.bullet_body.velocity = (tank.tank_body.rotation_vector) * self.speed 167 | self.bullet_shape.father = self 168 | self.max_time = 500 169 | self.time = self.max_time 170 | self.laserList = [self.bullet_body.position] 171 | self.bullet_shape.laserList = self.laserList 172 | def update(self, space): 173 | self.time -= 1 174 | if self.time <= 0 and self.bullet_shape in space.shapes: 175 | space.remove(self.bullet_shape.body, self.bullet_shape) 176 | bullets.remove(self) 177 | 178 | class Laser(): 179 | def __init__(self, p1, p2, color, rad=2): 180 | self.laser_body = pymunk.Body(body_type=pymunk.Body.STATIC) 181 | self.laser_body.position = p1 # (p1[0] + p2[0]) // 2, (p1[1] + p2[1]) // 2 182 | 183 | self.laser_shape = pymunk.Segment(self.laser_body, (0, 0), (p2[0] - p1[0], p2[1] - p1[1]), rad) 184 | self.laser_shape.density = 0.1 185 | self.laser_shape.elasticity = 1 186 | self.laser_shape.friction = 0 187 | self.laser_shape.color = pygame.Color(color) 188 | self.laser_shape.collision_type = collision_types["bullet"] 189 | self.bullet_shape = self.laser_shape 190 | self.bullet_shape.father = self 191 | self.broke_available = True 192 | self.max_time = 100 193 | self.time = self.max_time 194 | def update(self, space): 195 | self.time -= 1 196 | if self.time <= 0 and self.laser_shape in space.shapes: 197 | space.remove(self.laser_shape.body, self.laser_shape) 198 | bullets.remove(self) 199 | 200 | class RC(): 201 | def __init__(self, tank): 202 | self.speed = 120 203 | self.bullet_body = pymunk.Body() 204 | self.bullet_body.position = tank.tank_body.position + tank.tank_body.rotation_vector * 35 205 | self.tank = tank 206 | self.bullet_body.tank = tank 207 | self.bullet_body.father = self 208 | self.bullet_shape = pymunk.Circle(self.bullet_body, 10) 209 | self.bullet_shape.father = self 210 | self.bullet_shape.density = 0.1 211 | self.bullet_shape.elasticity = 0.1 212 | self.bullet_shape.friction = 0 213 | self.bullet_shape.color = pygame.Color("white") 214 | self.bullet_shape.collision_type = collision_types["missile"] 215 | 216 | if self.tank.tank_shape.color == (255, 0, 0, 100): 217 | self.ori_image = pygame.image.load("image/red_missile.png") 218 | else: 219 | self.ori_image = pygame.image.load("image/green_missile.png") 220 | self.rect = self.ori_image.get_rect() 221 | self.rect.center = self.bullet_body.position 222 | 223 | self.angle = calculate_angle((0, 0), self.tank.tank_body.rotation_vector) 224 | self.angle = 360 - math.degrees(self.angle) 225 | self.image = pygame.transform.rotate(self.ori_image, self.angle) 226 | self.rect = self.image.get_rect() 227 | self.rect.center = self.bullet_body.position 228 | 229 | self.bullet_body.velocity = (tank.tank_body.rotation_vector) * self.speed 230 | self.angular_velocity = 3 231 | self.time = 1000 232 | self.col_time = self.time 233 | def update(self, space): 234 | self.time -= 1 235 | # self.bullet_body.velocity = 0, 0 236 | self.bullet_body.angular_velocity = 0 237 | if self.time <= self.col_time - 10: 238 | self.bullet_body.velocity = self.tank.tank_body.rotation_vector * self.speed 239 | # self.bullet_body.apply_force_at_world_point(unitization(*self.bullet_body.velocity) * -1000, (0, 0)) 240 | # if math.hypot(*self.bullet_body.velocity) <= 170: 241 | # self.bullet_body.apply_force_at_world_point(self.tank.tank_body.rotation_vector * 3000, (0, 0)) 242 | # if math.hypot(*self.bullet_body.velocity) <= 100: 243 | # self.bullet_body.apply_impulse_at_world_point(self.tank.tank_body.rotation_vector * 300, (0, 0)) 244 | 245 | 246 | self.angle = calculate_angle((0, 0), self.tank.tank_body.rotation_vector) 247 | self.angle = 360 - math.degrees(self.angle) 248 | self.image = pygame.transform.rotate(self.ori_image, self.angle) 249 | self.rect = self.image.get_rect() 250 | self.rect.center = self.bullet_body.position 251 | 252 | # self.bullet_body.velocity = self.bullet_body.rotation_vector[1] * self.speed, self.bullet_body.rotation_vector[0] * -self.speed 253 | if self.time <= 0 and self.bullet_shape in space.shapes: 254 | space.remove(self.bullet_shape.body, self.bullet_shape) 255 | bullets.remove(self) 256 | def draw_image(self): 257 | if self.bullet_shape in space.shapes: 258 | window.blit(self.image, self.rect) 259 | 260 | class BrokenBullet(): 261 | def __init__(self, tank): 262 | self.bullet_body = pymunk.Body() 263 | self.bullet_body.position = tank.tank_body.position + tank.tank_body.rotation_vector * 24 264 | 265 | self.bullet_shape = pymunk.Circle(self.bullet_body, 3) 266 | self.bullet_shape.density = 0.1 267 | self.bullet_shape.elasticity = 1 268 | self.bullet_shape.friction = 0 269 | self.bullet_shape.color = pygame.Color("black") 270 | self.bullet_shape.collision_type = collision_types["brokenBullet"] 271 | self.bullet_shape.father = self 272 | 273 | self.speed = 170 274 | self.bullet_body.velocity = (tank.tank_body.rotation_vector) * self.speed 275 | self.broke_available = True 276 | self.time = 500 277 | 278 | def update(self, space): 279 | self.time -= 1 280 | if self.time <= 0 and self.bullet_shape in space.shapes: 281 | space.remove(self.bullet_shape.body, self.bullet_shape) 282 | bullets.remove(self) 283 | 284 | class Tank: 285 | def __init__(self, color): 286 | self.speed = 100 287 | self.angular_velocity = 3 288 | 289 | self.death_lasers = [] 290 | 291 | self.fire_available = False 292 | self.move_available = False 293 | self.rotate_available = False 294 | self.is_fire_death_laser = False 295 | self.is_fire_rc = False 296 | self.is_gatling = False 297 | self.is_scatter = False 298 | 299 | self.tank_body = pymunk.Body(body_type=pymunk.Body.DYNAMIC) 300 | self.tank_body.prop_type = 0 301 | self.tank_body.position = (random.randint(100, 1400), random.randint(100, 800)) 302 | self.tank_body.velocity = 0, 0 303 | self.tank_body.angular_velocity = 0 304 | self.tank_body.father = self 305 | self.elasticity = 0.2 306 | 307 | # tank_shape = pymunk.Poly.create_box(tank_body, (20, 15)) 308 | self.tank_shape = pymunk.Poly.create_box(self.tank_body, (28, 21)) 309 | self.tank_shape.density = 0.1 310 | self.tank_shape.elasticity = self.elasticity 311 | self.tank_shape.color = color 312 | self.tank_shape.collision_type = collision_types["tank"] 313 | 314 | self.tank_shape_2 = pymunk.Circle(self.tank_body, 7) 315 | self.tank_shape_2.density = 0.1 316 | self.tank_shape_2.elasticity = self.elasticity 317 | self.tank_shape_2.collision_type = collision_types["tank"] 318 | self.tank_shape_2.color = (int(color[0] * 200 / 255), int(color[1] * 200 / 255), int(color[2] * 200 / 255), color[3]) 319 | 320 | self.tank_shape_3 = pymunk.Segment(self.tank_body, (-5, 0), (20, 0), 2) 321 | self.tank_shape_3.density = 0.1 322 | self.tank_shape_3.elasticity = self.elasticity 323 | self.tank_shape_3.collision_type = collision_types["tank"] 324 | self.tank_shape_3.color = (int(color[0] * 123 / 255), int(color[1] * 123 / 255), int(color[2] * 123 / 255), color[3]) 325 | 326 | self.col_time = 0 327 | 328 | def fire(self): 329 | if self.tank_body.prop_type in (0, 1, 7, 8): 330 | if self.is_scatter: 331 | self.fire_scatter(Bullet) 332 | else: 333 | bullet = Bullet(self) 334 | space.add(bullet.bullet_body, bullet.bullet_shape) 335 | bullets.append(bullet) 336 | elif self.tank_body.prop_type == 2: 337 | self.fire_frag() 338 | elif self.tank_body.prop_type == 4: 339 | self.fire_laser() 340 | elif self.tank_body.prop_type == 5: 341 | self.fire_death() 342 | elif self.tank_body.prop_type == 6: 343 | self.fire_rc() 344 | elif self.tank_body.prop_type == 9: 345 | self.fire_broken() 346 | 347 | def fire_frag(self): 348 | if self.is_scatter: 349 | self.fire_scatter(FragBullet) 350 | else: 351 | bullet = FragBullet(self) 352 | space.add(bullet.bullet_body, bullet.bullet_shape) 353 | bullets.append(bullet) 354 | 355 | def fire_scatter(self, Type): 356 | vec = self.tank_body.rotation_vector 357 | angle = math.atan2(*vec[::-1]) 358 | angle = math.degrees(angle) 359 | for _ in range(5): 360 | bullet = Type(self) 361 | ang = angle + random.uniform(-15, 15) 362 | ang = math.radians(ang) 363 | bullet.bullet_body.velocity = Vec2d(math.cos(ang), math.sin(ang)) * bullet.speed 364 | space.add(bullet.bullet_body, bullet.bullet_shape) 365 | bullets.append(bullet) 366 | 367 | def fire_laser(self): 368 | if self.is_scatter: 369 | self.fire_scatter(LaserBullet) 370 | else: 371 | bullet = LaserBullet(self) 372 | space.add(bullet.bullet_body, bullet.bullet_shape) 373 | bullets.append(bullet) 374 | 375 | def fire_death(self): 376 | self.death_lasers.clear() 377 | if self.is_scatter: 378 | vec = self.tank_body.rotation_vector 379 | angle = math.atan2(*vec[::-1]) 380 | angle = math.degrees(angle) 381 | for _ in range(5): 382 | ang = angle -14 + _ * 7 383 | ang = math.radians(ang) 384 | p1 = self.tank_body.position + Vec2d(math.cos(ang), math.sin(ang)) * 30 385 | length = Vec2d(math.cos(ang), math.sin(ang)) * 2000 386 | p2 = p1[0] + length[0], p1[1] + length[1] 387 | laser = Laser(p1, p2, self.tank_shape.color, 4) 388 | space.add(laser.laser_body, laser.laser_shape) 389 | bullets.append(laser) 390 | self.death_laser = laser 391 | self.death_lasers.append(laser) 392 | else: 393 | p1 = self.tank_body.position + self.tank_body.rotation_vector * 30 394 | length = self.tank_body.rotation_vector * 2000 395 | p2 = p1[0] + length[0], p1[1] + length[1] 396 | laser = Laser(p1, p2, self.tank_shape.color, 4) 397 | space.add(laser.laser_body, laser.laser_shape) 398 | bullets.append(laser) 399 | self.death_laser = laser 400 | self.death_lasers.append(laser) 401 | self.is_fire_death_laser = True 402 | 403 | def fire_rc(self): 404 | rc = RC(self) 405 | space.add(rc.bullet_body, rc.bullet_shape) 406 | bullets.append(rc) 407 | self.rc = rc 408 | self.is_fire_rc = True 409 | 410 | def fire_broken(self): 411 | if self.is_scatter: 412 | self.fire_scatter(BrokenBullet) 413 | else: 414 | bullet = BrokenBullet(self) 415 | space.add(bullet.bullet_body, bullet.bullet_shape) 416 | bullets.append(bullet) 417 | 418 | def teleport(self): 419 | self.tank_body.position = self.tank_body.position + self.tank_body.rotation_vector * 50 420 | 421 | def update(self): 422 | if self.is_fire_death_laser: 423 | if self.death_laser.time <= 0: 424 | self.is_fire_death_laser = False 425 | self.move_available = False 426 | self.fire_available = False 427 | self.angular_velocity = 0.1 428 | if self.is_scatter: 429 | vec = self.tank_body.rotation_vector 430 | angle = math.atan2(*vec[::-1]) 431 | angle = math.degrees(angle) 432 | for _ in range(5): 433 | ang = angle - 14 + _ * 7 434 | ang = math.radians(ang) 435 | p1 = self.tank_body.position + Vec2d(math.cos(ang), math.sin(ang)) * 30 436 | length = Vec2d(math.cos(ang), math.sin(ang)) * 2000 437 | p2 = p1[0] + length[0], p1[1] + length[1] 438 | self.death_lasers[_].laser_body.position = p1 439 | self.death_lasers[_].laser_shape.unsafe_set_endpoints((0, 0), p2 - p1) 440 | if self.death_lasers[_].laser_shape in space.shapes: 441 | space.remove(self.death_lasers[_].laser_body, self.death_lasers[_].laser_shape) 442 | space.add(self.death_lasers[_].laser_shape, self.death_lasers[_].laser_body) 443 | else: 444 | p1 = self.tank_body.position + self.tank_body.rotation_vector * 30 445 | length = self.tank_body.rotation_vector * 2000 446 | p2 = p1[0] + length[0], p1[1] + length[1] 447 | self.death_laser.laser_body.position = p1 448 | self.death_laser.laser_shape.unsafe_set_endpoints((0, 0), p2 - p1) 449 | if self.death_laser.laser_shape in space.shapes: 450 | space.remove(self.death_laser.laser_body, self.death_laser.laser_shape) 451 | space.add(self.death_laser.laser_shape, self.death_laser.laser_body) 452 | # print(self.death_laser.laser_shape.a, self.death_laser.laser_shape.b) 453 | elif self.is_fire_rc: 454 | if self.rc.bullet_shape not in space.shapes: 455 | self.is_fire_rc = False 456 | self.move_available = False 457 | self.fire_available = False 458 | # self.rotate_available = False 459 | else: 460 | self.angular_velocity = 3 461 | 462 | def sub_tuple(p1, p2): 463 | return p1[0] - p2[0], p1[1] - p2[1] 464 | 465 | def time_stop(): 466 | for b in bullets: 467 | b.bullet_body.velocity = (0, 0) 468 | 469 | def unitization(x, y): 470 | # mo = math.sqrt(x ** 2 + y ** 2) 471 | # return Vec2d(x / mo, y / mo) 472 | return p2vec((0, 0), (x, y)) 473 | 474 | def p2vec(p1, p2): 475 | angle = calculate_angle(p1, p2) 476 | vec = (math.cos(angle), math.sin(angle)) 477 | return Vec2d(*vec) 478 | 479 | def calculate_distance(p1, p2): 480 | return math.sqrt((p2[1] - p1[1])**2 + (p2[0] - p1[0])**2) 481 | 482 | def calculate_angle(p1, p2): 483 | return math.atan2(p2[1] - p1[1], p2[0] - p1[0]) 484 | 485 | def draw(space, window, draw_options, line): 486 | if line: 487 | pygame.draw.line(window, "black", line[0], line[1], 3) 488 | space.debug_draw(draw_options) 489 | # 绘制道具 490 | for p in props: 491 | p.draw() 492 | for b in bullets: 493 | if hasattr(b, "draw_image"): 494 | b.draw_image() 495 | window.blit( 496 | font.render("red : %d" % red_win, True, pygame.Color("red")), 497 | (1400, 10) 498 | ) 499 | window.blit( 500 | font.render("green: %d" % green_win, True, pygame.Color("green")), 501 | (1400, 50) 502 | ) 503 | # window.blit(pygame.transform.rotate(tank1_img, 90 - np.angle(tank1.rotation_vector[0] + 1j*tank1.rotation_vector[1], deg=True)), tank1.position - (12, 7)) 504 | pygame.display.update() 505 | 506 | def create_boundaries(space, width, height): 507 | rects = [ 508 | [(width/2, height - 10), (width, 20)], 509 | [(width/2, 10), (width, 20)], 510 | [(10, height/2), (20, height)], 511 | [(width - 10, height/2), (20, height)], 512 | ] 513 | 514 | for pos, size in rects: 515 | body = pymunk.Body(body_type=pymunk.Body.STATIC) 516 | body.position = pos 517 | shape = pymunk.Poly.create_box(body, size) 518 | shape.elasticity = 0.4 519 | shape.friction = 1 520 | space.add(body, shape) 521 | 522 | def create_structure(space, width, height): 523 | BROWN = (139, 69, 19, 100) 524 | rects = [ 525 | [(600, height - 120), (40, 200), BROWN, 100], 526 | [(900, height - 120), (40, 200), BROWN, 100], 527 | [(750, height - 240), (340, 40), BROWN, 150], 528 | ] 529 | 530 | for pos, size, color, mass in rects: 531 | body = pymunk.Body() 532 | body.position = pos 533 | shape = pymunk.Poly.create_box(body, size, radius=2) 534 | shape.color = color 535 | shape.mass = mass 536 | shape.elasticity = 0.4 537 | space.add(body, shape) 538 | 539 | def create_ball(space, radius, pos): 540 | body = pymunk.Body() 541 | body.position = pos 542 | shape = pymunk.Circle(body, radius) 543 | shape.density = 0.1 544 | shape.elasticity = 1 545 | shape.friction = 0 546 | shape.color = (255, 0, 0, 100) 547 | space.add(body, shape) 548 | return shape 549 | 550 | def create_ret(space, pos, size, flag): 551 | body = pymunk.Body(body_type=pymunk.Body.STATIC) 552 | body.position = pos 553 | if flag == 0: 554 | # body.position = pos + (4//2, size//2) 555 | shape = pymunk.Poly.create_box(body, (4, size), radius=1) # 竖 556 | else: 557 | # body.position = pos + (size // 2, 4 // 2) 558 | shape = pymunk.Poly.create_box(body, (size, 4), radius=1) 559 | 560 | shape.elasticity = 1 561 | shape.density = 0.1 562 | shape.color = (77, 77, 77, 100) 563 | space.add(body, shape) 564 | return shape 565 | 566 | def create_seg(space, pos, size, flag): 567 | body = pymunk.Body(body_type=pymunk.Body.STATIC) 568 | body.position = pos 569 | rad = 4 570 | if flag == 0: 571 | shape = pymunk.Segment(body, (0, 0), (0, size), radius=rad) 572 | else: 573 | shape = pymunk.Segment(body, (0, 0), (size, 0), radius=rad) 574 | shape.collision_type = collision_types["wall"] 575 | shape.elasticity = 1 576 | shape.density = 0.1 577 | shape.color = (77, 77, 77, 100) 578 | space.add(body, shape) 579 | return shape 580 | 581 | # def create_map(space): 582 | # image = cv2.imread("image/10x10.png", cv2.IMREAD_GRAYSCALE) 583 | # image = cv2.resize(image, (image.shape[0]*2, image.shape[1]*2)) 584 | # map = image < 127 585 | # # map_body = pymunk.Body() 586 | # # space.add(map_body) 587 | # def sample_func(point): 588 | # x = int(point[0]) 589 | # y = int(point[1]) 590 | # return 1 if map[y][x] else 0 591 | # 592 | # pl_set = march_soft(pymunk.BB(0, 0, map.shape[0], map.shape[1]), map.shape[0], map.shape[1], .5, sample_func) 593 | # for poly_line in pl_set: 594 | # for i in range(len(poly_line) - 1): 595 | # a = poly_line[i] 596 | # b = poly_line[i + 1] 597 | # segment = pymunk.Segment(space.static_body, a, b, 1) 598 | # segment.density = 0.1 599 | # space.add(segment) 600 | # # for i in range(map.shape[0]): 601 | # # for j in range(map.shape[1]): 602 | # # if map[i][j]: 603 | # # create_ret(space, (j, i), (1, 1)) 604 | def create_map2(space): 605 | create_ret(space, (0,0), 164, 0) 606 | for _ in range(500): 607 | pos = (random.randint(0, 30) * 50, random.randint(0, 20) * 50) 608 | size = random.randint(1, 1) * 50 609 | flag = random.choice((0, 1)) 610 | create_seg(space, pos, size, flag) 611 | pass 612 | 613 | 614 | def create_tank(color): 615 | tank = Tank(color) 616 | space.add(tank.tank_shape, tank.tank_shape_2, tank.tank_shape_3, tank.tank_body) 617 | return tank 618 | 619 | def create_prop(): 620 | global props_num 621 | prop = Prop(random.choice(list(prop_types)), (random.randint(0, 1536), random.randint(0, 800))) 622 | props_num -= 1 623 | props.append(prop) 624 | 625 | def create_prop_by_mouse(prop_type): 626 | global props_num 627 | prop = Prop(prop_type, pygame.mouse.get_pos()) 628 | props.append(prop) 629 | 630 | def create_stick_figure(space): 631 | shapes = [] 632 | bodies = [] 633 | joints = [] 634 | 635 | # head = pymunk.Body() 636 | # bodies.append(head) 637 | # head.position = (300, 500) 638 | # head_shape = pymunk.Circle(head, 20) 639 | # shapes.append(head_shape) 640 | 641 | torso = pymunk.Body() 642 | bodies.append(torso) 643 | torso.position = (300, 520) 644 | torso_shape = pymunk.Segment(torso, (0, 0), (0, 70), 5) 645 | torso_shape.color = (0, 0, 200, 100) 646 | tou_shape = pymunk.Circle(torso, 20, (0, -20)) 647 | tou_shape.color = (200, 0, 0, 100) 648 | shapes.append(torso_shape) 649 | shapes.append(tou_shape) 650 | 651 | left_arm = pymunk.Body() 652 | bodies.append(left_arm) 653 | left_arm.position = (300, 520) 654 | left_arm_shape = pymunk.Segment(left_arm, (0, 0), (-25, 30), 5) 655 | left_arm_shape.color = (0, 0, 200, 100) 656 | shapes.append(left_arm_shape) 657 | 658 | left_arm_2 = pymunk.Body() # 左下臂 659 | bodies.append(left_arm_2) 660 | left_arm_2.position = (275, 550) 661 | left_arm_2_shape = pymunk.Segment(left_arm_2, (0, 0), (-25, 30), 5) 662 | left_arm_2_shape.collision_type = collision_types["stickBullet"] 663 | left_arm_2_shape.color = (200, 0, 0, 100) 664 | shapes.append(left_arm_2_shape) 665 | 666 | right_arm = pymunk.Body() 667 | bodies.append(right_arm) 668 | right_arm.position = (300, 520) 669 | right_arm_shape = pymunk.Segment(right_arm, (0, 0), (25, 30), 5) 670 | right_arm_shape.color = (0, 0, 200, 100) 671 | shapes.append(right_arm_shape) 672 | 673 | right_arm_2 = pymunk.Body() # 右下臂 674 | bodies.append(right_arm_2) 675 | right_arm_2.position = (325, 550) 676 | right_arm_2_shape = pymunk.Segment(right_arm_2, (0, 0), (25, 30), 5) 677 | right_arm_2_shape.collision_type = collision_types["stickBullet"] 678 | right_arm_2_shape.color = (200, 0, 0, 100) 679 | shapes.append(right_arm_2_shape) 680 | 681 | left_leg = pymunk.Body() 682 | bodies.append(left_leg) 683 | left_leg.position = (300, 590) 684 | left_leg_shape = pymunk.Segment(left_leg, (0, 0), (-25, 30), 6) 685 | left_leg_shape.color = (0, 0, 200, 100) 686 | shapes.append(left_leg_shape) 687 | 688 | left_leg_2 = pymunk.Body() 689 | bodies.append(left_leg_2) 690 | left_leg_2.position = (275, 620) 691 | left_leg_2_shape = pymunk.Segment(left_leg_2, (0, 0), (-25, 30), 6) 692 | left_leg_2_shape.collision_type = collision_types["stickBullet"] 693 | left_leg_2_shape.color = (200, 0, 0, 100) 694 | shapes.append(left_leg_2_shape) 695 | 696 | right_leg = pymunk.Body() 697 | bodies.append(right_leg) 698 | right_leg.position = (300, 590) 699 | right_leg_shape = pymunk.Segment(right_leg, (0, 0), (25, 30), 6) 700 | right_leg_shape.color = (0, 0, 200, 100) 701 | shapes.append(right_leg_shape) 702 | 703 | right_leg_2 = pymunk.Body() 704 | bodies.append(right_leg_2) 705 | right_leg_2.position = (325, 620) 706 | right_leg_2_shape = pymunk.Segment(right_leg_2, (0, 0), (25, 30), 6) 707 | right_leg_2_shape.collision_type = collision_types["stickBullet"] 708 | right_leg_2_shape.color = (200, 0, 0, 100) 709 | shapes.append(right_leg_2_shape) 710 | 711 | for shape in shapes: 712 | shape.friction = 1 713 | shape.mass = 3 714 | shape.elasticity = 1 715 | shape.filter = pymunk.ShapeFilter(group=1) 716 | 717 | # head_torso_joint = pymunk.PivotJoint(head, torso, (300, 500)) 718 | # joints.append(head_torso_joint) 719 | 720 | torso_left_arm_joint = pymunk.PivotJoint(torso, left_arm, (300, 520)) 721 | joints.append(torso_left_arm_joint) 722 | 723 | torso_right_arm_joint = pymunk.PivotJoint(torso, right_arm, (300, 520)) 724 | joints.append(torso_right_arm_joint) 725 | 726 | left_arm_12_joint = pymunk.PivotJoint(left_arm, left_arm_2, (275, 550)) 727 | joints.append(left_arm_12_joint) 728 | 729 | right_arm_12_joint = pymunk.PivotJoint(right_arm, right_arm_2, (325, 550)) 730 | joints.append(right_arm_12_joint) 731 | 732 | torso_left_leg_joint = pymunk.PivotJoint(torso, left_leg, (300, 590)) 733 | # torso_left_leg_RatchetJoint = pymunk.RatchetJoint(left_leg, torso, 0, math.pi / 3) 734 | joints.append(torso_left_leg_joint) 735 | # joints.append(torso_left_leg_RatchetJoint) 736 | 737 | torso_right_leg_joint = pymunk.PivotJoint(torso, right_leg, (300, 590)) 738 | # torso_right_leg_RatchetJoint = pymunk.RatchetJoint(right_leg, torso, 0, math.pi / 3) 739 | joints.append(torso_right_leg_joint) 740 | # joints.append(torso_right_leg_RatchetJoint) 741 | 742 | left_leg_12_joint = pymunk.PivotJoint(left_leg, left_leg_2, (275, 620)) 743 | left_leg_12_joint_2 = pymunk.RatchetJoint(left_leg_2, left_leg, 0, -math.pi) 744 | joints.append(left_leg_12_joint) 745 | joints.append(left_leg_12_joint_2) 746 | left_leg_12_joint_3 = pymunk.DampedRotarySpring(left_leg, left_leg_2, -math.pi, 3000, 60) 747 | joints.append(left_leg_12_joint_3) 748 | 749 | 750 | right_leg_12_joint = pymunk.PivotJoint(right_leg, right_leg_2, (325, 620)) 751 | right_leg_12_joint_2 = pymunk.RatchetJoint(right_leg_2, right_leg, 0, -math.pi) 752 | joints.append(right_leg_12_joint) 753 | joints.append(right_leg_12_joint_2) 754 | right_leg_12_joint_3 = pymunk.DampedRotarySpring(right_leg, right_leg_2, -math.pi, 3000, 60) 755 | joints.append(right_leg_12_joint_3) 756 | 757 | space.add(*bodies, *shapes, *joints) 758 | 759 | return torso 760 | 761 | def create_swing_ball(space): 762 | rotation_center_body = pymunk.Body(body_type=pymunk.Body.STATIC) 763 | rotation_center_body.position = (300, 300) 764 | 765 | body = pymunk.Body() 766 | body.position = (300, 300) 767 | line = pymunk.Segment(body, (0, 0), (255, 0), 5) 768 | circle = pymunk.Circle(body, 40, (255, 0)) 769 | line.friction = 1 770 | circle.friction = 1 771 | line.mass = 8 772 | circle.mass = 30 773 | circle.elasticity = 0.95 774 | rotation_center_joint = pymunk.PinJoint(body, rotation_center_body, (0, 0), (0, 0)) 775 | space.add(circle, line, body, rotation_center_joint) 776 | 777 | def restart(space, tank1, tank2): 778 | global props_num 779 | global game_time 780 | is_end = 0 781 | game_time = 0 782 | try: 783 | props.clear() 784 | bullets.clear() 785 | props_num = 5 786 | for item in space.shapes: 787 | space.remove(item) 788 | # space.remove(*tank1.tank_body.shapes, *tank2.tank_body.shapes, tank1.tank_body, tank2.tank_body) 789 | space.shapes.clear() 790 | except: 791 | pass 792 | for s in space.shapes[:]: 793 | try: 794 | space.remove(s.body, s) 795 | except: 796 | continue 797 | t1 = create_tank((255, 0, 0, 100)) 798 | t2 = create_tank((0, 255, 0, 100)) 799 | create_map2(space) 800 | 801 | return t1, t2, is_end 802 | 803 | def restart_train(space, tank1, tank2): 804 | global props_num 805 | global game_time 806 | is_end = 0 807 | game_time = 0 808 | try: 809 | props.clear() 810 | bullets.clear() 811 | props_num = 5 812 | for item in space.shapes: 813 | space.remove(item) 814 | # space.remove(*tank1.tank_body.shapes, *tank2.tank_body.shapes, tank1.tank_body, tank2.tank_body) 815 | space.shapes.clear() 816 | except: 817 | pass 818 | for s in space.shapes[:]: 819 | try: 820 | space.remove(s.body, s) 821 | except: 822 | continue 823 | t1 = create_tank((255, 0, 0, 100)) 824 | t2 = create_tank((0, 255, 0, 100)) 825 | 826 | return t1, t2, is_end 827 | 828 | def run(): 829 | run = True 830 | clock = pygame.time.Clock() 831 | fps = 60 832 | dt = 1 / fps 833 | 834 | # space.gravity = (0, 0) 835 | 836 | # create_boundaries(space, width, height) 837 | # create_structure(space, width, height) 838 | # stick_figure = create_stick_figure(space) 839 | tank1 = create_tank((255, 0, 0, 100)) 840 | tank2 = create_tank((0, 255, 0, 100)) 841 | # create_ball(space, 10, (50, 50)) 842 | 843 | draw_options = pymunk.pygame_util.DrawOptions(window) 844 | 845 | translation = pymunk.Transform() 846 | scaling = 1 847 | 848 | pressed_pos = None 849 | ball = None 850 | 851 | cnt = 1 852 | 853 | def remove_tank(arbiter, space, data): 854 | tank_shape = arbiter.shapes[0] 855 | space.remove(tank_shape) 856 | 857 | def remove_bullet(arbiter, space, data): 858 | bullet_shape = arbiter.shapes[1] 859 | tank_shape = arbiter.shapes[0] 860 | if hasattr(bullet_shape.body, 'explode'): 861 | bullet_shape.body.explode() 862 | # space.remove(bullet_shape, bullet_shape.body) 863 | remove_obj.add(bullet_shape) 864 | if bullet_shape in bullets: 865 | bullets.remove(bullet_shape) 866 | remove_obj.add(tank_shape) 867 | 868 | def remove_prop(arbiter, space, data): 869 | tank_shape = arbiter.shapes[0] 870 | prop_shape = arbiter.shapes[1] 871 | type = prop_shape.body.prop_type 872 | if type == prop_types["gatling"]: 873 | tank_shape.body.father.is_gatling = True 874 | elif type == prop_types["scatter"]: 875 | tank_shape.body.father.is_scatter = True 876 | else: 877 | tank_shape.body.prop_type = prop_shape.body.prop_type 878 | remove_obj.add(prop_shape) 879 | 880 | def reflect(arbiter, space, data): 881 | wall_shape = arbiter.shapes[1] 882 | laserBulletShape = arbiter.shapes[0] 883 | laserList = laserBulletShape.laserList 884 | if not laserBulletShape.body.position in laserList: 885 | laserList.append(laserBulletShape.body.position) 886 | laser = Laser(tuple(laserList[-1]), tuple(laserList[-2]), laserBulletShape.tank_color) 887 | space.add(laser.laser_body, laser.laser_shape) 888 | bullets.append(laser) 889 | 890 | def no_coll(arbiter, space, data): 891 | return False 892 | 893 | def set_velocity_zero(arbiter, space, data): # 阻止物体穿墙 894 | bullet_shape = arbiter.shapes[0] 895 | bullet_shape.father.col_time = bullet_shape.father.time 896 | 897 | def broke_wall(arbiter, space, data): 898 | bullet_shape = arbiter.shapes[0] 899 | wall_shape = arbiter.shapes[1] 900 | if bullet_shape.father.broke_available: 901 | # bullet_shape.father.broke_available = False 902 | remove_obj.add(wall_shape) 903 | 904 | def anti_col(arbiter, space, data): 905 | tank_shape = arbiter.shapes[0] 906 | if isinstance(tank_shape, pymunk.Segment): 907 | tank_shape.body.father.col_time = game_time 908 | 909 | def solve_bullet_through_wall(arbiter, space, data): 910 | bullet_shape = arbiter.shapes[0] 911 | if bullet_shape.father.max_time - bullet_shape.father.time <= 1: 912 | remove_obj.add(bullet_shape) 913 | 914 | def col_stick_tank(arbiter, space, data): 915 | bullet_shape = arbiter.shapes[1] 916 | tank_shape = arbiter.shapes[0] 917 | if bullet_shape in bullets: 918 | bullets.remove(bullet_shape) 919 | remove_obj.add(tank_shape) 920 | 921 | h1 = space.add_collision_handler(collision_types["tank"], collision_types["bullet"]) 922 | h2 = space.add_collision_handler(collision_types["tank"], collision_types["prop"]) 923 | h3 = space.add_collision_handler(collision_types["laserBullet"], collision_types["wall"]) 924 | h4 = space.add_collision_handler(collision_types["laserBullet"], collision_types["bullet"]) 925 | h5 = space.add_collision_handler(collision_types["laserBullet"], collision_types["tank"]) 926 | h6 = space.add_collision_handler(collision_types["laserBullet"], collision_types["prop"]) 927 | h7 = space.add_collision_handler(collision_types["bullet"], collision_types["prop"]) 928 | h8 = space.add_collision_handler(collision_types["laserBullet"], collision_types["laserBullet"]) 929 | h9 = space.add_collision_handler(collision_types["missile"], collision_types["wall"]) 930 | h10 = space.add_collision_handler(collision_types["missile"], collision_types["prop"]) 931 | h11 = space.add_collision_handler(collision_types["missile"], collision_types["tank"]) 932 | h12 = space.add_collision_handler(collision_types["brokenBullet"], collision_types["wall"]) 933 | h14 = space.add_collision_handler(collision_types["brokenBullet"], collision_types["tank"]) 934 | h15 = space.add_collision_handler(collision_types["brokenBullet"], collision_types["prop"]) 935 | h16 = space.add_collision_handler(collision_types["tank"], collision_types["wall"]) 936 | h17 = space.add_collision_handler(collision_types["bullet"], collision_types["wall"]) 937 | h18 = space.add_collision_handler(collision_types["tank"], collision_types["stickBullet"]) 938 | 939 | h1.post_solve = h11.post_solve = h14.post_solve = remove_bullet 940 | h2.post_solve = remove_prop 941 | h3.post_solve = reflect 942 | h4.begin = h5.begin = h6.begin = h7.begin = h8.begin = h10.begin = h15.begin = no_coll 943 | h9.post_solve = set_velocity_zero 944 | h12.post_solve = broke_wall 945 | h16.post_solve = anti_col 946 | h17.post_solve = solve_bullet_through_wall 947 | h18.post_solve = col_stick_tank 948 | 949 | create_map2(space) 950 | # restart_train(space, tank1, tank2) 951 | is_end = 0 952 | 953 | while run: 954 | global game_time 955 | global mouse_visible 956 | game_time += 1 957 | window.fill("white") 958 | line = None 959 | if cnt == 1: 960 | mouse_joint = None 961 | mouse_body = pymunk.Body(body_type=pymunk.Body.KINEMATIC) 962 | cnt = 0 963 | if ball and pressed_pos: 964 | line = [pygame.mouse.get_pos(), pressed_pos] 965 | 966 | # stick_figure.apply_force_at_world_point((0, -27000), stick_figure.position + (0, -100)) 967 | 968 | key = pygame.key.get_pressed() 969 | 970 | if tank1.tank_body.prop_type != 7: 971 | tank1.tank_body.velocity = 0, 0 972 | tank1.tank_body.angular_velocity = 0 973 | tank1.fire_available = False 974 | tank1.move_available = False 975 | tank1.rotate_available = False 976 | if tank2.tank_body.prop_type != 7: 977 | tank2.tank_body.velocity = 0, 0 978 | tank2.tank_body.angular_velocity = 0 979 | tank2.fire_available = False 980 | tank2.move_available = False 981 | tank2.rotate_available = False 982 | 983 | global red_win 984 | global green_win 985 | global props_num 986 | 987 | if props_num: 988 | create_prop() 989 | 990 | for tank in [tank1, tank2]: 991 | tank_shapes = tank.tank_body.shapes 992 | for item in tank_shapes: 993 | if isinstance(item, pymunk.shapes.Poly) and item in space.shapes: 994 | tank.move_available = True 995 | if isinstance(item, pymunk.shapes.Segment) and item in space.shapes: 996 | tank.fire_available = True 997 | if isinstance(item, pymunk.shapes.Circle) and item in space.shapes: 998 | tank.rotate_available = True 999 | tank.update() 1000 | 1001 | if not tank1.move_available and not tank1.fire_available and not tank1.rotate_available and is_end == 0: 1002 | green_win += 1 1003 | is_end = 1 1004 | if not tank2.move_available and not tank2.fire_available and not tank2.rotate_available and is_end == 0: 1005 | red_win += 1 1006 | is_end = 1 1007 | 1008 | # 红色坦克 1009 | if tank1.tank_body.prop_type == 7: 1010 | tank1.tank_body.apply_force_at_world_point(unitization(*tank1.tank_body.velocity) * -2000, (0, 0)) 1011 | if key[pygame.K_UP] and tank1.move_available: 1012 | if math.hypot(*tank1.tank_body.velocity) <= 120: 1013 | tank1.tank_body.apply_force_at_world_point(tank1.tank_body.rotation_vector * 5000, (0, 0)) 1014 | if math.hypot(*tank1.tank_body.velocity) <= 80: 1015 | tank1.tank_body.apply_impulse_at_local_point((300, 0), (0, 0)) 1016 | if key[pygame.K_DOWN] and tank1.move_available: 1017 | if math.hypot(*tank1.tank_body.velocity) <= 120: 1018 | tank1.tank_body.apply_force_at_world_point(tank1.tank_body.rotation_vector * -5000, (0, 0)) 1019 | if math.hypot(*tank1.tank_body.velocity) <= 80: 1020 | tank1.tank_body.apply_impulse_at_local_point((-300, 0), (0, 0)) 1021 | else: 1022 | if key[pygame.K_UP] and tank1.move_available and game_time - tank1.col_time >= 2: 1023 | tank1.tank_body.velocity = tank1.tank_body.rotation_vector * tank1.speed 1024 | if key[pygame.K_DOWN] and tank1.move_available: 1025 | tank1.tank_body.velocity = tank1.tank_body.rotation_vector * -tank1.speed 1026 | 1027 | if key[pygame.K_LEFT] and tank1.rotate_available: 1028 | tank1.tank_body.angular_velocity = -tank1.angular_velocity 1029 | if key[pygame.K_RIGHT] and tank1.rotate_available: 1030 | tank1.tank_body.angular_velocity = tank1.angular_velocity 1031 | 1032 | # 绿色坦克 1033 | if tank2.tank_body.prop_type == 7: 1034 | tank2.tank_body.apply_force_at_world_point(unitization(*tank2.tank_body.velocity) * -2000, (0, 0)) 1035 | if key[pygame.K_w] and tank2.move_available: 1036 | if math.hypot(*tank2.tank_body.velocity) <= 120: 1037 | tank2.tank_body.apply_force_at_world_point(tank2.tank_body.rotation_vector * 5000, (0, 0)) 1038 | if math.hypot(*tank2.tank_body.velocity) <= 80: 1039 | tank2.tank_body.apply_impulse_at_local_point((300, 0), (0, 0)) 1040 | if key[pygame.K_s] and tank2.move_available: 1041 | if math.hypot(*tank2.tank_body.velocity) <= 120: 1042 | tank2.tank_body.apply_force_at_world_point(tank2.tank_body.rotation_vector * -5000, (0, 0)) 1043 | if math.hypot(*tank2.tank_body.velocity) <= 80: 1044 | tank2.tank_body.apply_impulse_at_local_point((-300, 0), (0, 0)) 1045 | else: 1046 | if key[pygame.K_w] and tank2.move_available and game_time - tank2.col_time >= 2: 1047 | tank2.tank_body.velocity = tank2.tank_body.rotation_vector * tank2.speed 1048 | if key[pygame.K_s] and tank2.move_available: 1049 | tank2.tank_body.velocity = tank2.tank_body.rotation_vector * -tank2.speed 1050 | 1051 | 1052 | if key[pygame.K_a] and tank2.rotate_available: 1053 | tank2.tank_body.angular_velocity = -tank2.angular_velocity 1054 | if key[pygame.K_d] and tank2.rotate_available: 1055 | tank2.tank_body.angular_velocity = tank2.angular_velocity 1056 | 1057 | # if key[pygame.K_KP_ENTER]: 1058 | # fire(space, tank1) 1059 | # bullet.velocity = (tank1.rotation_vector) * 400 1060 | 1061 | for p in props: 1062 | p.update() 1063 | 1064 | for item in remove_obj.copy(): 1065 | if item in space.shapes: 1066 | space.remove(item) 1067 | remove_obj.clear() 1068 | 1069 | 1070 | for b in bullets: 1071 | b.update(space) 1072 | 1073 | left = int(key[pygame.K_KP_4]) 1074 | up = int(key[pygame.K_KP_8]) 1075 | down = int(key[pygame.K_KP_2]) 1076 | right = int(key[pygame.K_KP_6]) 1077 | zoom_in = int(key[pygame.K_x]) 1078 | zoom_out = int(key[pygame.K_z]) 1079 | 1080 | zoom_speed = 0.1 1081 | scaling *= 1 + (zoom_speed * zoom_in - zoom_speed * zoom_out) 1082 | 1083 | translate_speed = 10 1084 | translation = translation.translated( 1085 | translate_speed * left - translate_speed * right, 1086 | translate_speed * up - translate_speed * down, 1087 | ) 1088 | 1089 | draw_options.transform = ( 1090 | pymunk.Transform.scaling(scaling) 1091 | @ translation 1092 | ) 1093 | 1094 | for event in pygame.event.get(): 1095 | if event.type == pygame.QUIT: 1096 | run = False 1097 | break 1098 | 1099 | elif event.type == pygame.MOUSEBUTTONDOWN: 1100 | if mouse_joint is not None: 1101 | space.remove(mouse_joint) 1102 | mouse_joint = None 1103 | 1104 | p = Vec2d(*event.pos) 1105 | hit = space.point_query_nearest(p, 5, pymunk.ShapeFilter()) 1106 | if hit is not None and hit.shape.body.body_type == pymunk.Body.DYNAMIC: 1107 | shape = hit.shape 1108 | # Use the closest point on the surface if the click is outside 1109 | # of the shape. 1110 | if hit.distance > 0: 1111 | nearest = hit.point 1112 | else: 1113 | nearest = p 1114 | mouse_joint = pymunk.PivotJoint( 1115 | mouse_body, shape.body, (0, 0), shape.body.world_to_local(nearest) 1116 | ) 1117 | mouse_joint.max_force = 50000 1118 | mouse_joint.error_bias = (1 - 0.15) ** 60 1119 | space.add(mouse_joint) 1120 | 1121 | elif event.type == pygame.MOUSEBUTTONUP: 1122 | if mouse_joint is not None: 1123 | space.remove(mouse_joint) 1124 | mouse_joint = None 1125 | elif event.type == pygame.KEYDOWN and event.key == pygame.K_r: 1126 | tank1, tank2, is_end = restart(space, tank1, tank2) 1127 | elif event.type == pygame.KEYDOWN and event.key == pygame.K_t: 1128 | tank1, tank2, is_end = restart_train(space, tank1, tank2) 1129 | 1130 | if event.type == pygame.KEYDOWN and event.key == pygame.K_KP_ENTER and tank1.fire_available: 1131 | tank1.fire() 1132 | if event.type == pygame.KEYDOWN and event.key == pygame.K_KP_0 and tank1.tank_body.prop_type == 8 and tank1.rotate_available: 1133 | tank1.teleport() 1134 | 1135 | if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE and tank2.fire_available: 1136 | tank2.fire() 1137 | if event.type == pygame.KEYDOWN and event.key == pygame.K_f and tank2.tank_body.prop_type == 8 and tank2.rotate_available: 1138 | tank2.teleport() 1139 | 1140 | # 鼠标创造daoju 1141 | if event.type == pygame.KEYDOWN and event.key == pygame.K_1: 1142 | create_prop_by_mouse("gatling") 1143 | if event.type == pygame.KEYDOWN and event.key == pygame.K_2: 1144 | create_prop_by_mouse("frag") 1145 | if event.type == pygame.KEYDOWN and event.key == pygame.K_3: 1146 | create_prop_by_mouse("scatter") 1147 | if event.type == pygame.KEYDOWN and event.key == pygame.K_4: 1148 | create_prop_by_mouse("laser") 1149 | if event.type == pygame.KEYDOWN and event.key == pygame.K_5: 1150 | create_prop_by_mouse("death") 1151 | if event.type == pygame.KEYDOWN and event.key == pygame.K_6: 1152 | create_prop_by_mouse("rc") 1153 | if event.type == pygame.KEYDOWN and event.key == pygame.K_7: 1154 | create_prop_by_mouse("speed") 1155 | if event.type == pygame.KEYDOWN and event.key == pygame.K_8: 1156 | create_prop_by_mouse("teleport") 1157 | if event.type == pygame.KEYDOWN and event.key == pygame.K_9: 1158 | create_prop_by_mouse("broken") 1159 | 1160 | # 控制鼠标显示 1161 | if event.type == pygame.KEYDOWN and event.key == pygame.K_u: 1162 | mouse_visible = not mouse_visible 1163 | pygame.mouse.set_visible(mouse_visible) 1164 | # 时间静止 1165 | if event.type == pygame.KEYDOWN and event.key == pygame.K_p: 1166 | time_stop() 1167 | 1168 | if tank1.is_gatling and key[pygame.K_KP_ENTER] and tank1.fire_available: 1169 | tank1.fire() 1170 | if tank2.is_gatling and key[pygame.K_SPACE] and tank2.fire_available: 1171 | tank2.fire() 1172 | 1173 | 1174 | mouse_body.position = pygame.mouse.get_pos() 1175 | 1176 | draw(space, window, draw_options, line) 1177 | 1178 | space.step(dt) 1179 | clock.tick(fps) 1180 | 1181 | pygame.quit() 1182 | 1183 | 1184 | if __name__ == "__main__": 1185 | run() 1186 | 1187 | -------------------------------------------------------------------------------- /游戏说明.txt: -------------------------------------------------------------------------------- 1 | - 正常游玩需要知道的: 2 | - wasd+空格+f(瞬移)控制绿坦克 3 | - 方向键+小键盘enter键+小键盘0(瞬移)控制红坦克 4 | - r键重新开始 5 | - t键创建空白地图 6 | - 正常游玩不需要知道的: 7 | - u键隐藏鼠标 8 | - p键炮弹速度置0 9 | - 123456789键在鼠标位置生成道具 10 | - z键和x键控制缩放(不建议使用) 11 | - 小键盘2468键控制摄像头移动(不建议使用) 12 | - 鼠标可以拖动某些物体(不建议使用) --------------------------------------------------------------------------------