Python is a dynamic and strongly typed language that supports many programming paradigms, such as procedural, object oriented, and functional programming.

Python has been implemented in several different ways; the standard interpreter in C (CPython), in python itself (PyPy), in the .Net Dynamic Language Runtime (C#) (IronPython), and in Java on the Java Virtual Machine (Jython). Jython comes with java interoperability; allowing it to leverage powerful java libraries, such as Libgdx, while keeping the succinctness and readability of Python.

This article uses the latest Jython beta (Jython 2.7b1 available here), this release aims to bring compatilibity with CPython 2.7, so we will be programming with Python 2.7 syntax in this article.

Note: at the time of writting, you can only use Jython with libGDX on the desktop.

Setup

Jython can be worked on with any text editor, including Vim or Emacs. PyDev is an option for eclipse users. Once the environment is setup, create a new Jython project, and all of the libGDX dependencies to the PYTHONPATH. for using the desktop LWJGL backend, this includes gdx.jar, gdx-backend-lwjgl.jar, gdx-backend-lwjgl-natives.jar, gdx-natives.jar, and gdx-sources.jar.

Coding With Python

The entirety of the Drop Tutorial can be contained into a single python file.

  1. from com.badlogic.gdx.backends.lwjgl import LwjglApplication, LwjglApplicationConfiguration
  2. from com.badlogic.gdx.utils import TimeUtils, Array
  3. from com.badlogic.gdx.math import MathUtils, Rectangle, Vector3
  4. from com.badlogic.gdx import ApplicationListener, Gdx, Input
  5. from com.badlogic.gdx.graphics.g2d import SpriteBatch
  6. from com.badlogic.gdx.graphics import Texture, OrthographicCamera, GL20
  7. class PyGdx(ApplicationListener):
  8. def __init__(self):
  9. self.camera = None
  10. self.batch = None
  11. self.texture = None
  12. self.bucketimg = None
  13. self.dropsound = None
  14. self.rainmusic = None
  15. self.bucket = None
  16. self.raindrops = None
  17. self.lastdrop = 0
  18. self.width = 800
  19. self.height = 480
  20. def spawndrop(self):
  21. raindrop = Rectangle()
  22. raindrop.x = MathUtils.random(0, self.width - 64)
  23. raindrop.y = self.height
  24. raindrop.width = 64
  25. raindrop.height = 64
  26. self.raindrops.add(raindrop)
  27. self.lastdrop = TimeUtils.nanoTime()
  28. def create(self):
  29. self.camera = OrthographicCamera()
  30. self.camera.setToOrtho(False, self.width, self.height)
  31. self.batch = SpriteBatch()
  32. self.dropimg = Texture("assets/droplet.png")
  33. self.bucketimg = Texture("assets/bucket.png")
  34. self.dropsound = Gdx.audio.newSound(Gdx.files.internal("assets/drop.wav"))
  35. self.rainmusic = Gdx.audio.newSound(Gdx.files.internal("assets/rain.mp3"))
  36. self.bucket = Rectangle()
  37. self.bucket.x = (self.width / 2) - (64 / 2)
  38. self.bucket.y = 20
  39. self.bucket.width = 64
  40. self.bucket.height = 64
  41. self.raindrops = Array()
  42. self.spawndrop()
  43. self.rainmusic.setLooping(True, True)
  44. self.rainmusic.play()
  45. def render(self):
  46. Gdx.gl.glClearColor(0,0,0.2,0)
  47. Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
  48. self.camera.update()
  49. self.batch.setProjectionMatrix(self.camera.combined)
  50. self.batch.begin()
  51. self.batch.draw(self.bucketimg, self.bucket.x, self.bucket.y)
  52. for drop in self.raindrops:
  53. self.batch.draw(self.dropimg, drop.x, drop.y)
  54. self.batch.end()
  55. if Gdx.input.isTouched():
  56. touchpos = Vector3()
  57. touchpos.set(Gdx.input.getX(), Gdx.input.getY(), 0)
  58. self.camera.unproject(touchpos)
  59. self.bucket.x = touchpos.x - (64 / 2)
  60. if Gdx.input.isKeyPressed(Input.Keys.LEFT): self.bucket.x -= 200 * Gdx.graphics.getDeltaTime()
  61. if Gdx.input.isKeyPressed(Input.Keys.RIGHT): self.bucket.x += 200 * Gdx.graphics.getDeltaTime()
  62. if self.bucket.x < 0: self.bucket.x = 0
  63. if self.bucket.x > (self.width - 64): self.bucket.x = self.width - 64
  64. if (TimeUtils.nanoTime() - self.lastdrop) > 1000000000: self.spawndrop()
  65. iterator = self.raindrops.iterator()
  66. while iterator.hasNext():
  67. raindrop = iterator.next()
  68. raindrop.y -= 200 * Gdx.graphics.getDeltaTime();
  69. if (raindrop.y + 64) < 0: iterator.remove()
  70. if raindrop.overlaps(self.bucket):
  71. self.dropsound.play()
  72. iterator.remove()
  73. def resize(self, width, height):
  74. pass
  75. def pause(self):
  76. pass
  77. def resume(self):
  78. pass
  79. def dispose(self):
  80. self.batch.dispose()
  81. self.dropimg.dispose()
  82. self.bucketimg.dispose()
  83. self.dropsound.dispose()
  84. self.rainmusic.dispose()
  85. def main():
  86. cfg = LwjglApplicationConfiguration()
  87. cfg.title = "PyGdx";
  88. cfg.width = 800
  89. cfg.height = 480
  90. LwjglApplication(PyGdx(), cfg)
  91. if __name__ == '__main__':
  92. main()

note that during asset creation we need to specifiy the assets/ folder. When not using android, we must specify the folder structure that we use, whereas on android all internal assets are assumed to be in the assets/ directory.

Games written in Python using libGDX

  • none (yet! if you have made a game using python in libgdx, please let me know and edit this article!)