Python – динамический и строго типизированный язык, который поддерживает множество парадигм программирования, таких как процедурное, объектно-ориентированное и функциональное программирование.
Python был реализован несколькими различными способами: стандартный интерпретатор на C (CPython), на самом Python (PyPy), на .Net DLR (C#) (IronPython) и на Java с JVM (Jython). Jython поставляется с Java совместимостью, что позволяет использовать мощные Java библиотеки, такие как libGDX, при этом сохраняя лаконичность и читаемость языка Python.
В этой статье используется последняя бета версия Jython (Jython 2.7b1), этот релиз нацелен на совместимость с CPython 2.7, поэтому в этой статье мы будет программировать с синтаксисом Python 2.7.
Jython и libGDX
На момент написания статьи, использование Jython и libGDX возможно только на персональном компьютере.
Установка
С Jython можно работать в любом тестовом редакторе, в том числе в Vim или Emacs. PyDev вариант для пользователей
Eclipse. Как только настроена среда разработки, создайте новый Jython проект и задайте все libGDX зависимости в PYTHONPATH, для использования LWJGL
backend персонального компьютера. Это включает gdx.jar
, gdx-backend-lwjgl.jar
, gdx-backend-lwjgl-natives.jar
,
gdx-backend-lwjgl.jar
, gdx-natives.jar
и gdx-sources.jar
.
Программирование на Python
Полный урок простой игры может содержаться в одно python файле.
from com.badlogic.gdx.backends.lwjgl import LwjglApplication, LwjglApplicationConfiguration from com.badlogic.gdx.utils import TimeUtils, Array from com.badlogic.gdx.math import MathUtils, Rectangle, Vector3 from com.badlogic.gdx import ApplicationListener, Gdx, Input from com.badlogic.gdx.graphics.g2d import SpriteBatch from com.badlogic.gdx.graphics import Texture, OrthographicCamera, GL10 class PyGdx(ApplicationListener): def __init__(self): self.camera = None self.batch = None self.texture = None self.bucketimg = None self.dropsound = None self.rainmusic = None self.bucket = None self.raindrops = None self.lastdrop = 0 self.width = 800 self.height = 480 def spawndrop(self): raindrop = Rectangle() raindrop.x = MathUtils.random(0, self.width - 64) raindrop.y = self.height raindrop.width = 64 raindrop.height = 64 self.raindrops.add(raindrop) self.lastdrop = TimeUtils.nanoTime() def create(self): self.camera = OrthographicCamera() self.camera.setToOrtho(False, self.width, self.height) self.batch = SpriteBatch() self.dropimg = Texture("assets/droplet.png") self.bucketimg = Texture("assets/bucket.png") self.dropsound = Gdx.audio.newSound(Gdx.files.internal("assets/drop.wav")) self.rainmusic = Gdx.audio.newSound(Gdx.files.internal("assets/rain.mp3")) self.bucket = Rectangle() self.bucket.x = (self.width / 2) - (64 / 2) self.bucket.y = 20 self.bucket.width = 64 self.bucket.height = 64 self.raindrops = Array() self.spawndrop() self.rainmusic.setLooping(True, True) self.rainmusic.play() def render(self): Gdx.gl.glClearColor(0,0,0.2,0) Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT) self.camera.update() self.batch.setProjectionMatrix(self.camera.combined) self.batch.begin() self.batch.draw(self.bucketimg, self.bucket.x, self.bucket.y) for drop in self.raindrops: self.batch.draw(self.dropimg, drop.x, drop.y) self.batch.end() if Gdx.input.isTouched(): touchpos = Vector3() touchpos.set(Gdx.input.getX(), Gdx.input.getY(), 0) self.camera.unproject(touchpos) self.bucket.x = touchpos.x - (64 / 2) if Gdx.input.isKeyPressed(Input.Keys.LEFT): self.bucket.x -= 200 * Gdx.graphics.getDeltaTime() if Gdx.input.isKeyPressed(Input.Keys.RIGHT): self.bucket.x += 200 * Gdx.graphics.getDeltaTime() if self.bucket.x < 0: self.bucket.x = 0 if self.bucket.x > (self.width - 64): self.bucket.x = self.width - 64 if (TimeUtils.nanoTime() - self.lastdrop) > 1000000000: self.spawndrop() iterator = self.raindrops.iterator() while iterator.hasNext(): raindrop = iterator.next() raindrop.y -= 200 * Gdx.graphics.getDeltaTime(); if (raindrop.y + 64) < 0: iterator.remove() if raindrop.overlaps(self.bucket): self.dropsound.play() iterator.remove() def resize(self, width, height): pass def pause(self): pass def resume(self): pass def dispose(self): self.batch.dispose() self.dropimg.dispose() self.bucketimg.dispose() self.dropsound.dispose() self.rainmusic.dispose() def main(): cfg = LwjglApplicationConfiguration() cfg.title = "PyGdx"; cfg.width = 800 cfg.height = 480 LwjglApplication(PyGdx(), cfg) if __name__ == '__main__': main()
Отметим, что во время создания asset, нужно указать assets/
директорию. Когда не используется Android, мы должны указывать
структуру директорий, которую мы используем. В то время как на Android считается, что все внутренние asset ресурсы находятся в assets/
директории.