Scan to open on your phone
Point a camera at the QR code - it opens this exact paste, no app needed.
https://codepastes.com/zzgsgxm3471b13jk無題Plain Text
import pygame
import sys
import random
import math
# --- 設定 ---
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 700
FPS = 60
# カラー定義 (数字が大きくなるほど色が変化)
COLORS = {
2: (240, 128, 128), # 薄赤
4: (255, 165, 0), # オレンジ
8: (238, 232, 170), # 黄
16: (152, 251, 152), # 緑
32: (135, 206, 250), # 青
64: (186, 85, 211), # 紫
128: (255, 105, 180), # ピンク
256: (255, 0, 0) # 赤
}
# 出現する基本の数字リスト
SPAWN_VALUES = [2, 4, 8]
# --- クラス定義 ---
class Blob:
def __init__(self, x, y, value):
self.x = x
self.y = y
self.value = value
self.radius = int(math.log2(value)) * 8 + 12 # 値が大きいほどサイズアップ
self.vy = 0 # 自由落下の速度
self.is_dropped = False
self.color = COLORS.get(value, (255, 255, 255))
def update(self):
if self.is_dropped:
self.vy += 0.5 # 重力
self.y += self.vy
# 地面との衝突
if self.y + self.radius > SCREEN_HEIGHT - 20:
self.y = SCREEN_HEIGHT - 20 - self.radius
self.vy = 0
def draw(self, screen, font):
# 本体を描画
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius)
pygame.draw.circle(screen, (255, 255, 255), (int(self.x), int(self.y)), self.radius, 2)
# 数字を描画
text = font.render(str(self.value), True, (0, 0, 0))
text_rect = text.get_rect(center=(int(self.x), int(self.y)))
screen.blit(text, text_rect)
# --- メイン処理 ---
def main():
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("sobosuba Like Merge Game")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 24)
score = 0
blobs = []
# 次に落とすBlobを生成(修正:SPAWN_VALUESを追加)
current_blob = Blob(SCREEN_WIDTH // 2, 80, random.choice(SPAWN_VALUES))
running = True
while running:
screen.fill((30, 30, 30)) # 背景(ダークグレー)
# 上部の待機ライン・地面の描画
pygame.draw.line(screen, (100, 100, 100), (0, 120), (SCREEN_WIDTH, 120), 2)
pygame.draw.rect(screen, (50, 50, 50), (0, SCREEN_HEIGHT - 20, SCREEN_WIDTH, 20))
# イベント処理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# マウス移動で投下位置を変更(落とす前のみ)
if event.type == pygame.MOUSEMOTION and not current_blob.is_dropped:
current_blob.x = max(current_blob.radius, min(event.pos[0], SCREEN_WIDTH - current_blob.radius))
# クリックで落下開始
if event.type == pygame.MOUSEBUTTONDOWN and not current_blob.is_dropped:
current_blob.is_dropped = True
blobs.append(current_blob)
# 次のBlobをセット(修正:SPAWN_VALUESを追加)
current_blob = Blob(event.pos[0], 80, random.choice(SPAWN_VALUES))
# 移動制限(次のBlobが端に行き過ぎないように)
if not current_blob.is_dropped:
mx, _ = pygame.mouse.get_pos()
current_blob.x = max(current_blob.radius, min(mx, SCREEN_WIDTH - current_blob.radius))
current_blob.draw(screen, font)
# 既存のBlobの更新と描画
for blob in blobs:
blob.update()
# 衝突・マージ判定
merged_blobs = []
to_remove = set()
for i in range(len(blobs)):
if i in to_remove: continue
for j in range(i + 1, len(blobs)):
if j in to_remove: continue
b1 = blobs[i]
b2 = blobs[j]
# 2つの円の距離を計算
dist = math.hypot(b1.x - b2.x, b1.y - b2.y)
min_dist = b1.radius + b2.radius
if dist < min_dist:
# 同じ数字ならマージ
if b1.value == b2.value:
to_remove.add(i)
to_remove.add(j)
# 中間地点に新しいBlobを生成
new_x = (b1.x + b2.x) / 2
new_y = (b1.y + b2.y) / 2
new_value = b1.value * 2
score += new_value
new_blob = Blob(new_x, new_y, new_value)
new_blob.is_dropped = True
merged_blobs.append(new_blob)
break
else:
# 違う数字なら、めり込まないように位置を押し返す(超簡易擬似物理)
overlap = min_dist - dist
angle = math.atan2(b2.y - b1.y, b2.x - b1.x)
if b2.is_dropped and b2.vy == 0: # 下が固定されているなら上を押し上げる
b1.x -= math.cos(angle) * overlap
b1.y -= math.sin(angle) * overlap
else:
b2.x += math.cos(angle) * overlap / 2
b2.y += math.sin(angle) * overlap / 2
b1.x -= math.cos(angle) * overlap / 2
b1.y -= math.sin(angle) * overlap / 2
# 削除と新規マージ分の適用
blobs = [b for idx, b in enumerate(blobs) if idx not in to_remove]
blobs.extend(merged_blobs)
# 全て描画
for blob in blobs:
blob.draw(screen, font)
# スコア表示
score_text = font.render(f"SCORE: {score}", True, (255, 255, 255))
screen.blit(score_text, (20, 20))
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()
5,561 chars · codepastes.com