質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

解決済

ブロック崩しゲームを作成しています。パドルにボールが跳ね返るときに角度をあたる位置によって変えたいのですが変えることができません。また、動作中にボールが欠けることがあります。この不具合を解消したいです

Simonde
Simonde

総合スコア7

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1回答

0リアクション

0クリップ

2131閲覧

投稿2020/10/12 05:26

ブロック崩しゲームを作成してます。パドルとボールを使ってブロックを崩すという動作を作ることはできました。でも、ボールをパドルで跳ね返すときに、反射角が常に一定になってしまいます。パドルのあたる位置によってボールの反射角を変更したいです。またボールが動作中にたまにかけてしまうことがあります。この不具合を解消したいです。

from tkinter import * from dataclasses import dataclass import time import random #初期状態の設定 DURATION = 0.01 #描画間隔 PADDLE_X0 = 200 #パドルの初期位置x PADDLE_Y0 = 550 #パドルの初期位置y BALL_Y0 = 300       # ボールの初期位置y PAD_VX = 10 #パドルの速度 BALL_VX = 5 #ボールの速度 BALL_VY = 5 #ボールの速度 BLOCK_X = 100 #ブロックの位置x BLOCK_Y = 100 #ブロックの位置y BLOCK_W = 100 #ブロックの幅 BLOCK_H = 20 #ブロックの高さ NUM_BLOCKS = 7 #ブロックの位置 #変える色を用意する COLORS = ["blue", "red", "black", "white", "green", "pink", "orange"] @dataclass class Paddle: id: int x : int y : int w : int h : int v : int c : str @dataclass class Ball: id: int x : int y : int d : int vx: int vy: int c : str @dataclass class Block: id: int x : int y : int w : int h : int c : str @dataclass class Game: start: int #--------------------------------- #ball #ボールの描画・登録 def make_ball(x, y, d, vx, vy, c="black"): id = canvas.create_oval(x, y, x + d, y + d, fill=c, outline=c) return Ball(id, x, y, d, vx, vy, c) #ボールの移動(左右) def move_ball(ball): ball.x += ball.vx ball.y += ball.vy #ボールの再描画 def redraw_ball(ball): canvas.coords(ball.id, ball.x, ball.y, ball.x + ball.d, ball.y + ball.d) #paddle #パドルの描画・登録 def make_paddle(x, y, w , v, h, c="blue"): id = canvas.create_rectangle(x, y, x + w, y + h, fill=c, outline=c) return Paddle(id, x, y, w, h, v, c) #パドルの移動(左右) def move_paddle(pad): pad.x += pad.v #パドルの再描画 def redraw_paddle(pad): canvas.coords(pad.id, pad.x, pad.y, pad.x + pad.w, pad.y + pad.h) #block #ブロックの描画・登録 def make_block(x, y, m=40, n=300, c="green"): id = canvas.create_rectangle(x, y, x + m, y + n, fill=c, outline=c) return Block(id, x, y, m, n, c) #複数のブロックを生成する def make_blocks(n_rows, x0, y0, w, h, pad=10): blocks = [] for x in range(n_rows): blocks.append(make_block(x0, y0, w, h)) x0 = x0 + w + pad return blocks #ブロックを消す def delete_block(block): canvas.delete(block.id) def game_start(event): game.start = True #------------------------------------------------- #wall #壁の作成 def make_walls(ox, oy, width, height): canvas.create_rectangle(ox, oy, ox + width, oy + height) #--------------------------------------------------------- #パドル操作のイベントハンドラ def left_paddle(event): #速度を左向きに設定 paddle.v = -PAD_VX def right_paddle(event): #速度を右向きに設定 paddle.v = PAD_VX def stop_paddle(event): #速度を0に設定 paddle.v = 0 def change_paddle_color(pad, c="red"): canvas.itemconfigure(pad.id, fill=c) canvas.itemconfigure(pad.id, outline=c) redraw_paddle(pad) tk = Tk() canvas = Canvas(tk, width=1000, height=800, bd=0) canvas.pack() tk.update() paddle = make_paddle(PADDLE_X0, PADDLE_Y0, 100, PAD_VX, 10) ball = make_ball(200, BALL_Y0, 10, BALL_VX, BALL_VX) make_walls(100, 100, 800, 600) blocks = make_blocks(NUM_BLOCKS, BLOCK_X, BLOCK_Y, BLOCK_W, BLOCK_H) game = Game(False) #イベントと、イベントハンドラを連結する canvas.bind_all('<KeyPress-Left>', left_paddle) canvas.bind_all('<KeyPress-Right>', right_paddle) canvas.bind_all('<KeyRelease-Left>', stop_paddle) canvas.bind_all('<KeyRelease-Right>', stop_paddle) canvas.bind_all('<KeyPress-space>', game_start) #spaceが押された #---------------------------------------------------------------- #SPACEの入力待ち id_text = canvas.create_text(400, 200, text = "Press 'SPACE' to start", font = ('FixedSys', 16)) tk.update() while not game.start: #ひたすらSPACEを待つ tk.update() time.sleep(DURATION) canvas.delete(id_text) #SPACE入力のメッセージを削除 tk.update() #プログラムのメインループ while True: move_paddle(paddle) # move_ball(ball) if ball.y + ball.vy <= 100: #ボールが上端についた ball.vy = -ball.vy if ball.y + ball.d >= 600: #ボールが下端についた break if (ball.x + ball.vx < 100 \ or ball.x + ball.d >= 900): ball.vx = -ball.vx for block in blocks: #ボールのX位置がブロックに届き、Y位置もっブロックの範囲内 if ( block.x <= ball.x <=block.x + block.w \ and block.y <= ball.y <= block.y + block.h): ball.vx = -ball.vx #ボールを跳ね返す delete_block(block) #ブロックを消す blocks.remove(block) #ブロックのリストからこのブロックを削除 break if blocks == []:break #blocksリストが空になったら終了 #ボールがパドルの上端に届き、ボールの幅がパドルの幅に収まっている if (ball.y + ball.d >= paddle.y \ and paddle.x <= ball.x <= paddle.x + paddle.w): ball.vy = -ball.vy redraw_paddle(paddle) #パドルの再描画 redraw_ball(ball) #ボールの再描画 tk.update() #描画が画面に反映される time.sleep(DURATION) #次に描画するまで、sleepする

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

ozwk

2020/10/12 05:48

> パドルのあたる位置によってボールの反射角を変更したいです 質問はなんでしょう? 例) 「こういうふうに書いてみたけどエラーが出る」 「コードを書く以前の段階で、自分の思い描いた状況を具体的に言語化出来ない」 「いい感じのアルゴリズム考えてそれを実装したコードください」(丸投げ)
Simonde

2020/10/12 06:19

言葉たらずですみません。 パドルにボールが当たる位置によって角度が変わるようにしたいのですが、どのような関数?を使えばいいのか見当がつきません。言語化するにあたって考え方のヒントのようなものをいただけたら嬉しいです。
ozwk

2020/10/12 06:33

パドルの中央位置を0としたパドルとボールの接触点のx軸方向の位置 ボールの入射角度 ボールの反射角度 の関係を具体的に決めてください
Simonde

2020/10/12 09:55

a = math.atan(ball.vy/ (abs(paddle.x + paddle.w/2 - ball.x))) という関数?を作り 下の条件文 #ボールがパドルの上端に届き、ボールの幅がパドルの幅に収まっている if (ball.y + ball.d >= paddle.y \ and paddle.x <= ball.x <= paddle.x + paddle.w): ball.vy = -ball.vy a = math.atan(ball.vy/ball.vx) のところの末尾にこのように入れて実行してみたのですが変化がありませんでした。 |paddle.x + paddle.w/2 - ball.x|はパドルの中心からボールの接触した点の距離を表しています。 どこが間違っているのでしょうか。
Simonde

2020/10/12 10:48

いろいろ考え直して実行することができました!

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。