Denner Logo Denner v1.7.1
📚 Official Documentation

Denner Language
Reference

SwiftやPython、JavaScriptにインスパイアされた、クリーンな構文を持つモダンな静的型付けスクリプト言語のリファレンスガイド。

🛡️ 静的型付け
🚀 即時実行
🏗️ モジュールシステム
🌐 URLインポート
🧱 クラスサポート
📖

Dennerとは

Dennerは、静的型付けとシンプルな構文を両立したスクリプト言語です。独自のツリーウォーキング・インタープリタにより、コンパイル不要で即座にコードを実行できます。

機能説明
🚀 高速起動Node.js上で動作する軽量なインタープリタ。数ミリ秒で実行開始。
🛡️ 静的型付け強力な型推論と明示的な型注釈により、バグを未然に防ぎます。
🏗️ モジュールimport/exportによる名前空間の分離。URLインポートにも対応。
🧱 クラスOOPサポート。class、this、メソッドを使った設計が可能。
🌐 Webブラウザブラウザ上で直接Dennerを実行できるPlayground対応。
📦

インストール

ワンライナーでDenner CLIをインストールできます。

🍎 macOS / Linux
curl -fsSL https://raw.githubusercontent.com/
rits1019c1/denner/refs/heads/main/install.sh
| sh
🪟 Windows (PowerShell)
powershell -ExecutionPolicy Bypass -Command 
"irm ...install.ps1 | iex"
💡
インターネット不要: Playgroundでブラウザ上から即座にDennerを試すこともできます。

基本コマンド

コマンド説明
denner run <file>スクリプトを実行
dennerインタラクティブREPLを起動
denner update最新バージョンに更新
denner install <version>特定バージョンをインストール
denner list利用可能なバージョン一覧を表示
denner --version現在のバージョンを表示
📝

変数 & 型

変数は型推論により自動的に型が決まります。明示的な型注釈も使用できます。

denner
// 型推論
x         = 10          // num (整数)
pi        = 3.14        // num (小数)
name      = "Denner"    // str
isActive  = true        // bool
items     = [1, 2, 3]   // list

// 文字列補間 {変数名} で埋め込み
log.print("Hello, {name}! x = {x}")

型一覧

型説明例
num整数・浮動小数点数42, 3.14
str文字列"hello"
bool真偽値true, false
list配列[1, 2, 3]
void戻り値なし(関数用)—
any任意の型—
➕

演算子

種類演算子例
算術+ - * / %10 + 3 * 2
比較== != < > <= >=x > 5
論理&& || !a && b
代入=x = 10
範囲n..m0..10(0以上10未満)
🔀

制御フロー

denner
// if / else if / else
score = 85
if score >= 90 {
    log.print("A")
} else if score >= 70 {
    log.print("B")
} else {
    log.print("C")
}

// while ループ
i = 0
while i < 5 {
    log.print(i)
    i = i + 1
}

// for 範囲ループ (0..n は0以上n未満)
for i in 0..10 {
    log.print(i)
}

// for イテレーション
fruits = ["apple", "banana", "cherry"]
for fruit in fruits {
    log.print(fruit)
}
⚙️

関数

関数はfunctionキーワードで定義します。引数と戻り値に型注釈を付けることができます。

denner
// 基本的な関数
function add(a: num, b: num): num {
    return a + b
}

// 再帰関数
function factorial(n: num): num {
    if n <= 1 { return 1 }
    return n * factorial(n - 1)
}

// 呼び出し
result = add(3, 4)               // 7
log.print("5! = {factorial(5)}")  // 120
🧱

クラス

classキーワードでクラスを定義できます。thisで自分自身のプロパティにアクセスします。

denner
class Animal {
    name: str
    sound: str

    function speak() {
        log.print("{this.name} says {this.sound}!")
    }
}

dog = Animal()
dog.name  = "Rex"
dog.sound = "woof"
dog.speak()  // Rex says woof!
ℹ️
現在のDennerではコンストラクタ引数に対応していません。インスタンス生成後にプロパティを設定してください。
📦

モジュール

importでモジュールを読み込み、exportで公開できます。URLからのインポートにも対応しています。

denner — lib.den
// lib.den
export function multiply(a: num, b: num): num {
    return a * b
}
denner — main.den
// main.den
import "./lib"

result = multiply(3, 7)
log.print(result)  // 21

// URLインポートも可能
import "https://raw.githubusercontent.com/.../lib.den"
🎨

モジュール: gui

ゲーム開発やグラフィック描画のための強力なモジュールです。ピクセル単位の描画と毎秒60フレームのメインループをサポートします。

描画メソッド

メソッド説明
gui.setup(w, h)キャンバスを初期化します(幅 w 、高さ h )。
gui.clear(color)画面全体を指定した色で塗りつぶします(背景クリア)。
gui.fillRect(x, y, w, h, c?)塗りつぶされた四角形を描画します。
gui.rect(x, y, w, h, color)枠線のみの四角形を描画します。
gui.roundRect(x, y, w, h, r, c)角が丸い四角形を描画します( r は半径)。
gui.gradient(x,y,w,h, c1, c2, v?)グラデーションで塗りつぶします( v は垂直/水平)。
gui.circle(x, y, r, color)塗りつぶされた円を描画します( r は半径)。
gui.line(x1, y1, x2, y2, c, lw?)直線を引きます( lw は線の太さ)。
gui.text(txt, x, y, c, sz?, f?)テキストを描画します( sz :サイズ, f :フォント)。
gui.textCenter(txt, x, y, c, sz?)中心座標を指定してテキストを中央寄せで描画します。
gui.image(url, x, y, w, h)指定URLの画像をロードして描画します(非同期)。

入力 & 状態管理

メソッド説明
gui.isKeyPressed(key)指定したキー( "ArrowUp" 等)が現在押されていれば true を返します。
gui.get_last_key()最後に押された、または離されたキーの名前を取得します。
gui.width() / gui.height()現在のキャンバスの幅と高さを返します。
gui.loop(callback)毎フレーム(1/60s)実行されるメインループを開始します。
denner — 基本的なゲームループ
import "gui"
pos_x = 0

function update() {
    gui.clear("#0f0f1a")
    gui.fillRect(pos_x, 250, 50, 50, "#8b5cf6")
    pos_x = pos_x + 2
    if pos_x > 800 { pos_x = 0 }
}

gui.loop(update)
📝

組み込み: list メソッド

リスト型(配列)で使用できる組み込みメソッドです。list.method() の形式で呼び出せます。

メソッド説明
l.push(v)リストの末尾に値 v を追加します。
l.pop()リストの末尾から要素を取り出し、その値を返します。
l.unshift(v)リストの先頭に値 v を追加します。
l.shift()リストの先頭から要素を取り出し、その値を返します。
l.length()リストの現在の要素数を返します( l.length プロパティも可)。
l.join(sep)全要素を指定の区切り文字 sep で繋いで文字列にします。
l.slice(s, e)インデックス s から e の範囲をコピーした新しいリストを作ります。
l.reverse()リストの要素の順序を反転させます(破壊的)。
l.includes(v)値 v がリストに含まれているか判定します( true / false )。
l.indexof(v)値 v が最初に見つかったインデックスを返します(なければ -1 )。
🔤

組み込み: string メソッド

文字列型(str)には、以下のメソッドがデフォルトで組み込まれており、"text".method() の形式で呼び出すことができます。モジュールのインポートは不要です。

メソッド説明
s.upper() / s.lower()文字列をすべて大文字または小文字に変換します。
s.length()文字列の文字数を返します。
s.trim()文字列の前後にある空白(スペース、タブ、改行)を除去します。
s.includes(q)文字列が q を含んでいるか判定します( true / false )。
s.startswith(p) / s.endswith(p)文字列が特定の文字列 p で始まっているか、または終わっているか判定します。
s.split(sep)文字列を区切り文字 sep で分割し、リストを返します。
s.replace(f, r)最初に見つかった f を r に置換します。
s.substring(s, e)インデックス s から e の直前までの部分文字列を返します。
s.substr(s, l)インデックス s から l 文字分の部分文字列を返します。
s.charat(i)インデックス i の位置にある文字を返します。
s.repeat(n)文字列を n 回繰り返した新しい文字列を返します。
s.padstart(l, c) / s.padend(l, c)文字列が指定の長さ l になるよう、先頭または末尾を c で埋めます。
🌐

組み込み: net

import "net"でHTTP通信やサーバー機能を使用できます。

⚠️
net.serveはNode.js環境(CLI)専用です。ブラウザPlaygroundでは通信のみ(net.get)動作します。
関数説明
net.get(url)HTTP GETリクエストを送信し、レスポンスを返します。
net.serve(port, handler)指定ポートでHTTPサーバーを起動します。

net.serve の使い方

サーバーを起動すると、指定した handler 関数がリクエストごとに実行されます。

net.serve(8080, function(url) {
    log.print("Request: " + url)
    
    if url == "/" {
        return "Hello, Denner Server!"
    }
    
    // HTMLタグを直接返すことも可能です
    return "<h1>Not Found</h1>"
})
🔢

組み込み: 数学演算

Dennerでは基本的な算術演算子が直接使用できます。

denner
a = 10 + 3    // 13
b = 10 - 3    // 7
c = 10 * 3    // 30
d = 10 / 3    // 3.333...
e = 10 % 3    // 1 (余り)
💻

組み込み: os

import "os"でOSに関する情報を取得できます。

関数説明
os.name()現在のプラットフォーム名を返します(darwin/linux/win32/browser)
os.env(key)環境変数の値を返します
📁

組み込み: path

import "path"でファイルパスの操作を行えます。

関数説明
path.join(...p)複数のパスを結合して1つのパスにします。
path.basename(p)パスからファイル名部分(末尾)を抽出します。
path.dirname(p)パスからディレクトリ部分を抽出します。
path.extname(p)パスから拡張子(.txt等)を抽出します。
📟

組み込み: cli

import "cli"でターミナル入力を扱えます。

関数説明
cli.input(p)プロンプトを表示してユーザーの入力を1行読み取ります。
cli.get_key()キー入力があるまで待機し、そのキーを返します。
🧱

GUIオブジェクト操作

gui.add() で生成したオブジェクトは、ただの静止画ではなく、「生きている物理オブジェクト」です。変数に保存することで、ゲーム中にその状態を自由に変更できます。

操作できるプロパティ

生成したオブジェクトの変数を通じて、以下の値を読み書きできます。

プロパティ説明実例
obj.x, obj.y現在位置。直接書き換えるとワープします。p.x = 400
obj.dx, obj.dy移動速度(デルタ)。毎フレームこの分だけ自動で移動します。p.dy = -5
obj.w, obj.hオブジェクトの幅と高さ。p.w = 100
obj.colorオブジェクトの色を動的に変更します。p.color = "red"
💡
テクニック: ball.dx = 0 - ball.dx と書くことで、速度のプラスマイナスを反転させ、「跳ね返り」を簡単に実現できます。

オブジェクトを消去する (gui.remove)

敵を倒した時やアイテムを拾った時は、gui.remove(obj) を使って画面から即座に取り除けます。消されたオブジェクトは、衝突判定の対象からも自動的に外れます。

⚡

イベント駆動開発

「何かが起きたとき」にだけ処理を走らせるのが イベント駆動プログラミング です。gui.loop の中で if 文を書きすぎるのを防ぎ、コードをスッキリと綺麗に保つことができます。

denner
// 🖱️ クリックされた瞬間に弾を発射する例
gui.on("click", function(x, y) {
    bullet = gui.add({ tag: "circle", x: player.x, y: player.y, r: 5 })
    bullet.dy = -10
})

// ⌨️ キーが押された瞬間の処理
gui.on("keydown", function(key) {
    if key == "Space" { player.jump() }
})
📐

ゲーム開発ガイド: 衝突判定

Dennerでは、面倒な座標計算を行わずに 「当たった瞬間」 に処理を実行できる強力なイベント駆動システムが用意されています。

1. 自動衝突判定 (おすすめ)

gui.add() で作成したオブジェクト同士が当たったとき、自動的に "collision" イベントが発生します。

denner
// オブジェクトの生成
ball = gui.add({ tag: "circle", x: 400, y: 300, r: 10, color: "white" })
paddle = gui.add({ tag: "rect", x: 400, y: 550, w: 80, h: 15, color: "blue" })

// 💥 衝突イベント。自分(o1)と相手(o2)が渡されます
gui.on("collision", function(o1, o2) {
    if o1 == ball {
        log.print("Hit!")
        ball.dy = 0 - ball.dy // 跳ね返る
    }
})
💡
ヒント: オブジェクトを消したい場合は gui.remove(o2) と書くだけで、ブロックなどを画面から消去できます。

2. プログラムの終了 (exit)

ゲームオーバー時や特定の条件でプログラムをピタッと止めたいときは、exit() を呼びます。

denner
if ball.y > 600 {
    log.print("Game Over")
    exit() // 🛑 プログラムを終了して停止する
}
💡
重要: めり込み防止(座標リセット)
衝突時に速度 dy を反転させるだけでなく、ball.y = target.y - 10 のように座標を少し戻すことで、多重衝突バグ(ブルブル震えたり突き抜けたりする現象)を確実に防げます。

3. 手動での判定 (AABB)

独自の複雑な計算が必要な場合は、四角形の重なり(AABB理論)を直接コードで書くこともできます。

denner
function hits(r1x, r1y, r1w, r1h, r2x, r2y, r2w, r2h): bool {
    return r1x < r2x + r2w && r1x + r1w > r2x &&
           r1y < r2y + r2h && r1y + r1h > r2y
}
🍱

逆引き!実践レシピ

ゲーム開発でよく使う「お決まりのパターン」を集めました。コピペして組み合わせてみましょう。

🚀 画面の左右で跳ね返らせる

if ball.x < 0 or ball.x > 790 { 
    ball.dx = 0 - ball.dx 
}

🏆 スコアを画面に表示し続ける

gui.loop の中で、毎フレームクリアした直後に描画します。

gui.loop(function() {
    gui.clear("#000")
    gui.text("SCORE: " + score, 20, 40, "white", 24)
})

🧱 たくさんのブロックを作る (2次元ループ)

for r in 0..4 {
    for c in 0..8 {
        gui.add({ tag: "rect", x: c*90+40, y: r*30+60, w: 80, h: 20, color: "red" })
    }
}

3. 手動での判定 (AABB)

独自の複雑な計算が必要な場合は、四角形の重なり(AABB理論)を直接コードで書くこともできます。

denner
function hits(r1x, r1y, r1w, r1h, r2x, r2y, r2w, r2h): bool {
    return r1x < r2x + r2w && r1x + r1w > r2x &&
           r1y < r2y + r2h && r1y + r1h > r2y
}
function circlesHit(x1, y1, r1, x2, y2, r2): bool { dist = gui.get_distance({x:x1, y:y1}, {x:x2, y:y2}) return dist < (r1 + r2) }
ball.dy = 0 - ball.dy if o2.tag == "rect" { gui.remove(o2) } } }) gui.loop(function() { gui.clear("#0f0f1a") ball.x = ball.x + ball.dx ball.y ball.y + ball.dy if ball.y > 600 { exit() } // 🛑 落ちたら終了 })