2007年5月4日金曜日

砲弾の射出(d3module)

目標地点を指定すると、そのために必要な射出方向を計算する。
射出速度は一定なので、遠方を狙うほど早く着弾する。
// ang ... 角度, pos ... 位置(座標), velo... 速さ
// distance ... 距離, b ... 放物線の第2係数
#include "d3m.hsp"
#module powModule
#defcfunc pow double d1, int i2, local st
    st = 1.0
    repeat i2
        st *= d1
    loop
    return st
#global

#const GRAVITY  1.0                                 // 重力加速度
#const VELOCITY 30.1                                // 射出速度
#const DISTANCE_MAX VELOCITY * VELOCITY / GRAVITY   // 最大飛距離

#const GRID_MAX         8   // グリッドの本数
#const GRID_DISTANCE    100 // グリッドの間隔
#const TARGET_RADIUS    10  // 照準の半径
#const BULLET_RADIUS    8   // 砲弾の半径

    screen 0480480

    // 射出点の座標
    posCannonX = double(GRID_MAX) * GRID_DISTANCE / 2
    posCannonY = 0.0
    posCannonZ = 0.0

    // 照準の座標
    posTargetX = double(GRID_MAX) * GRID_DISTANCE / 2
    posTargetY = double(GRID_MAX) * GRID_DISTANCE / 2
    posTargetZ = 0.0

    d3setcam GRID_MAX * GRID_DISTANCE / 2, -300200GRID_MAX * GRID_DISTANCE / 2GRID_MAX * GRID_DISTANCE / 20

*main
    gosub *move
    gosub *draw
    wait 4
    goto *main

*move
    stick key, 15
    if key & 16 : gosub *shot

    // 照準の移動
    posTargetX += 10 * (((key >> 2) & 1) - (key & 1))
    posTargetY += 10 * (((key >> 1) & 1) - ((key >> 3) & 1))

    // 砲弾の移動
    if posBulletZ >= 0 {
        posBulletX += veloBulletX
        posBulletY += veloBulletY
        posBulletZ += veloBulletZ
        veloBulletZ -= GRAVITY
    }
    return

*shot
    // 射出 ここらへんのスクリプトの理解は力学と微分の知識が要ります
    posBulletX = posCannonX
    posBulletY = posCannonY
    posBulletZ = posCannonZ
    angBullet = atan(posTargetY - posCannonY, posTargetX - posCannonX)
    distance = limitf(sqrt(pow(posTargetX - posCannonX, 2) + pow(posTargetY - posCannonY, 2)), 0.0DISTANCE_MAX)
    b = DISTANCE_MAX / distance + sqrt(pow(DISTANCE_MAX / distance, 2) - 1)

    veloBulletR = sqrt(GRAVITY * distance / b / 2)
    veloBulletZ = b * veloBulletR
    veloBulletX = veloBulletR * cos(angBullet)
    veloBulletY = veloBulletR * sin(angBullet)
    return

*draw
    redraw 0
    color : boxf
    color 0255                // グリッド
    repeat GRID_MAX + 1
        d3line cnt * GRID_DISTANCE00cnt * GRID_DISTANCEGRID_MAX * GRID_DISTANCE0
        d3line 0cnt * GRID_DISTANCE0GRID_MAX * GRID_DISTANCEcnt * GRID_DISTANCE0
    loop

    color 255                   // 照準
    d3circle posTargetX, posTargetY, posTargetZ, TARGET_RADIUS0

    if posBulletZ >= 0 {
        color 00255         // 砲弾
        d3circle posBulletX, posBulletY, posBulletZ, BULLET_RADIUS
        color 191191191     // 影
        d3circle posBulletX, posBulletY, 0BULLET_RADIUS
    }
    redraw 1
    return

0 件のコメント: