Skip to content

Instantly share code, notes, and snippets.

@yusuke
Forked from kishida/NightBirdFrame.java
Last active July 18, 2022 23:01
Show Gist options
  • Save yusuke/ea1f20c1284690322a558af3e560d853 to your computer and use it in GitHub Desktop.
Save yusuke/ea1f20c1284690322a558af3e560d853 to your computer and use it in GitHub Desktop.
Night Bird
//******************************************************************************
// NightBirdFrame.java: JFrame
// Copyright Kishida Naoki
//******************************************************************************
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.Serial;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collector;
import javax.swing.JFrame;
import javax.swing.Timer;
//==============================================================================
// アプレット NightBird のメインクラス
//
//==============================================================================
public class NightBirdFrame extends JFrame{
public static void main(String[] args) {
new NightBirdFrame().init();
}
//
//--- 鳥の形のデータ ---
//
//胴体
record PolyPoint(double x, double y){
static PolyPoint of(double x, double y){
return new PolyPoint(x, y);
}
}
static final List<PolyPoint> bPolyBodyHalf = List.of(
PolyPoint.of(0, 0),
PolyPoint.of(0, 2),
PolyPoint.of(1, 5),
PolyPoint.of(4, 11),
PolyPoint.of(9, 14),
PolyPoint.of(18, 14),
PolyPoint.of(22, 13),
PolyPoint.of(24, 9),
PolyPoint.of(24, 6),
PolyPoint.of(22, 3),
PolyPoint.of(21, 0)
);
static final List<PolyPoint> bPolyBody;
static{
bPolyBody = new ArrayList<>(bPolyBodyHalf);
for (int i = bPolyBodyHalf.size() - 1; i >= 0; i--) {
var e = bPolyBodyHalf.get(i);
bPolyBody.add(PolyPoint.of(e.x, -e.y));
}
}
//はね
static final PolyPoint[] bPolyWing = {
PolyPoint.of(6,-4),
PolyPoint.of(12,-4),
PolyPoint.of(10, -20),
PolyPoint.of(6,-10)};
@Serial
private static final long serialVersionUID = 1L;
List<PolyPoint> polyBody;
PolyPoint[] polyLWing = new PolyPoint[4];
PolyPoint[] polyRWing = new PolyPoint[4];
//
//--- 定数 ---
//
static final double pai = 6.283;
static final double eyeY = 100; //視点の高さ
static final double scrZ = 100; //画面の距離
static final int rotMax = 300; //回転の精度
static final int wingMax = 5; //はねの動きの精度
static final double birdY = 40; //鳥の高さ
static final double birdRate = 1.8;//鳥の大きさ
//
//--- 変数 ---
//
transient Image backbuf;
transient Graphics backbufgra; //内部描画バッファ
int m_width, m_height; //画面の大きさ
int centerX, centerY; //画面の中心
double rot;
double eyeX; //視点の座標
int[][] ground = new int[80][80];//地面のつぶつぶ
double birdX; //鳥の位置
int roll; //回転の長さ
int birdmove; //鳥の動き
int wing; //はねの角度
//--------------------------------------------------------------------------
public void init() {
setTitle("Night Duke");
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
m_width = getSize().width;
m_height = getSize().height;
centerX = m_width / 2;
centerY = m_height / 2;
rot = rotMax / 8d;
//内部描画バッファの用意
if (backbuf == null) {
backbuf = new BufferedImage(m_width, m_height, BufferedImage.TYPE_INT_RGB);
backbufgra = backbuf.getGraphics();
}
//地面
for (int i = 0; i < 80; i++) {
for (int j = 0; j < 80; j++) {
if (Math.random() > .99) {
ground[i][j] = 1;
} else {
ground[i][j] = 0;
}
}
}
//鳥のデータ
polyBody = bPolyBody.stream().map(e -> PolyPoint.of(e.x * birdRate, e.y * birdRate)).toList();
for (int i = 0; i < 4; i++) {
polyLWing[i] = PolyPoint.of(bPolyWing[i].x * birdRate,
bPolyWing[i].y * birdRate);
polyRWing[i] = PolyPoint.of(polyLWing[i].x, -polyLWing[i].y);
}
new Timer(50, ev -> draw()).start();
setVisible(true);
}
// NightBird 描画ハンドラ
//--------------------------------------------------------------------------
@Override
public void paint(Graphics g) {
g.drawImage(backbuf, 0, 0, this);
}
//描画
//----------------------------------------------------------------------------
public void draw() {
double co, si;
//前に進む
eyeX += 4;
while (eyeX > 80) {
eyeX -= 80;
}
//視点の回転
if (roll > 0) {
//回転中
rot++;
if (rot >= rotMax) {
rot = 0;
}
roll--;
} else {
if (Math.random() > .98) {
//回転開始
roll = (int) (Math.random() * 20) + 10;
}
}
if (birdmove == 0) {
//鳥がはばたいているとき
wing++;
if (wing >= wingMax) {
wing = 0;
//後ろに下がるかどうか判定
if (Math.random() > .92) {
birdmove = (int) (Math.random() * 15) + 10;
}
}
if (birdX < 0) {
birdX += 1;
}
} else {
//鳥が後ろに下がっているとき
birdmove--;
birdX -= 1;
}
//
//--- 画面描画 ---
//
//画面のクリア
backbufgra.setColor(Color.black);
backbufgra.fillRect(0, 0, m_width, m_height);
//地面の描画
backbufgra.setColor(Color.red);
co = Math.cos(Math.PI * 2 * rot / rotMax);
si = Math.sin(Math.PI * 2 * rot / rotMax);
for (int y = centerY + 20; y < m_height; y++) {
double dispx, dispy;
double groundx, groundz;
double matx, matz;
int meshx, meshz;
dispy = centerY - y;
groundz = -eyeY * scrZ / dispy;
if (groundz > 250) {
continue;
}
for (int x = 0; x < m_width; x++) {
dispx = x - centerX;
groundx = (dispx * groundz / scrZ);
matz = (groundx * co + (groundz - scrZ) * si + scrZ) / 4;
while (matz < 0) {
matz += 80;
}
meshz = (int) matz % 80;
matx = (-groundx * si + groundz * co) / 4 + eyeX;
while (matx < 0) {
matx += 80;
}
meshx = (int) matx % 80;
if (ground[meshx][meshz] == 1) {
//backbufgra.drawRect(x,y,1,1);
backbufgra.drawLine(x, y, x, y);
}
}
}
//鳥の描画
backbufgra.setColor(new Color(192, 192, 192));
int[] polyX = new int[polyBody.size()];
int[] polyY = new int[polyBody.size()];
double bx, by, bz;
double px, py, pz;
double ax, ay, az;//計算用
double wco, wsi;
double wpi;//はねの角度
double bodyY;//胴体の位置
//はねの角度の計算
wpi = pai * (.22 * Math.sin(pai * wing / wingMax) + .25);
wsi = Math.sin(wpi);
wco = Math.cos(wpi);
//鳥の上下運動
bodyY = -wco * 2;
//胴体
for (int i = 0; i < polyBody.size(); i++) {
var bodyPoint = polyBody.get(i);
bx = -bodyPoint.x + birdX;
bz = bodyPoint.y;
px = -bx * si + bz * co;
pz = bx * co + bz * si;
polyX[i] = (int) (px * scrZ / (scrZ + pz)) + centerX;
polyY[i] = -(int) ((birdY + bodyY) * scrZ / (scrZ + pz)) + centerY;
}
backbufgra.fillPolygon(polyX, polyY, polyBody.size());
//右の翼
for (int i = 0; i < 4; i++) {
bx = -polyRWing[i].x + birdX;
bz = polyRWing[i].y;
az = bz - polyRWing[0].y;
ay = 0;
bz = wsi * az + polyRWing[0].y;
by = wco * az;
px = -bx * si + bz * co;
pz = bx * co + bz * si;
polyX[i] = (int) (px * scrZ / (scrZ + pz)) + centerX;
polyY[i] = -(int) ((birdY + by + bodyY) * scrZ / (scrZ + pz)) + centerY;
}
backbufgra.fillPolygon(polyX, polyY, 4);
//左の翼
for (int i = 0; i < 4; i++) {
bx = -polyLWing[i].x + birdX;
bz = polyLWing[i].y;
az = bz - polyLWing[0].y;
ay = 0;
bz = wsi * az + polyLWing[0].y;
by = -wco * az;
px = -bx * si + bz * co;
pz = bx * co + bz * si;
polyX[i] = (int) (px * scrZ / (scrZ + pz)) + centerX;
polyY[i] = -(int) ((birdY + by + bodyY) * scrZ / (scrZ + pz)) + centerY;
}
backbufgra.fillPolygon(polyX, polyY, 4);
repaint();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment