Package: nyan
NyanNyan - a fork ofPython Play- is an open-source code library for the Python programming language that makes it as easy as possible to start making games. Here's the code to make a simple game using Nyan:importnyancat=nyan.new_text('=^.^=',font_size=70)@nyan.repeat_foreverasyncdefmove_cat():cat.x=nyan.random_number(-200,200)cat.y=nyan.random_number(-200,200)cat.color=nyan.random_color()cat.show()awaitnyan.sleep(seconds=0.4)cat.hide()awaitnyan.sleep(seconds=0.4)@cat.when_clickeddefwin_function():cat.show()cat.text='You won!'nyan.start_program()The code above makes a game where you have to click the cat to win:Nyan is an excellent choice for beginner programmers to get started with graphics programming. It was designed to have similar commands and simplicity toMIT's Scratchand is distinguished from such projects as Pygame, Arcade, or Pygame Zero because of its lack of boiler plate code, its easy-to-understand plain-english commands, and intuitive API.How to install NyanMake sure that you have Python 3.7 or greater. Run the following command in your terminal:pip install nyanHow to use NyanAll Nyan programs start withimport nyanand end withnyan.start_program(), like this:importnyan# this is the first line in the programnyan.start_program()# this is the last line in the programAll other commands go between those two commands.CommandsThe rest of this document is divided into the following sections:Basic Commands- Getting graphics, shapes, and text on the screen. Also changing the backdrop.Animation and Control Commands- Animating and controlling graphics, shapes, and text.Sprite Commands- Controlling sprites.Mouse Commands- Detecting mouse actions (clicks, movement).Keyboard Commands- Detecting keyboard actions.Audio Commands- Playing sounds and music.Other Useful Commands- General commands.Packaging Nyan Programs- Creating an executable that can be shared with other people.Basic CommandsTo get images or text on the screen, use the following commands. (Copy and paste the code below to try it out.)nyan.new_rect()box=nyan.new_rect(color='black',x=0,y=0,width=100,height=200,border_color="light blue",border_width=10)This will put a tall, black Rectangle in the middle of the screen.If you want to change where the image is on the screen, try changingx=0(horizontal position) andy=0(vertical position). Just like Scratch, the middle of the screen is x=0, y=0. Increasing x moves the image right and decreasing x moves the image left. Likeswise, increasing y moves the image up and decreasing y moves the image down. You can also change the color by changing'black'to another color name, like'orange'.nyan.new_image()character=nyan.new_image(image='character.png',x=0,y=0,size=100)This will place an image in the middle of the screen. Make sure you have a file namedcharacter.pngin a folder namedassetsinside your project for the code above to work. You can find images online at sites likeOpenGameArt, or you can make your own using an online sprite editor likePiskel.nyan.new_text()greeting=nyan.new_text(text='hi there',x=0,y=0,font=None,font_size=50,color='black')This will put some text on the screen.If you want to change the font, you'll need a font file (usually named something likeArial.ttf) in your assets folder. Then you can changefont=Nonetofont='Arial.ttf'. You can find font files at sites likeDaFont.nyan.new_circle()ball=nyan.new_circle(color='black',x=0,y=0,radius=100,border_color="light blue",border_width=10)This will put a black circle in the middle of the screen.nyan.set_backdrop()You can change the background color with thenyan.set_backdrop()command:nyan.set_backdrop('light blue')There arelots of named colors to choose from. Additionally, if you want to set colors by RGB (Red Green Blue) values, you can do that like this:# Sets the background to white. Each number can go from 0 to 255nyan.set_backdrop((255,255,255))Anywhere you can set a color in Nyan, you can do it using a named color like'red'or an RGB value above like(255, 255, 255)or even an RGBA value like(0, 0, 0, 127)(the fourth number is transparency from 0 to 255).Animation and Control Commands@nyan.repeat_foreverTo make things move around, you can start by using@nyan.repeat_forever, like this:cat=nyan.new_text('=^.^=')@nyan.repeat_foreverdefdo():cat.turn(10)The above code will make the cat turn around forever. Sprites have other commands that you can see in the next section called Sprite Commands.@nyan.when_program_startsTo make some code run just at the beginning of your project, use@nyan.when_program_starts, like this:cat=nyan.new_text('=^.^=')@nyan.when_program_startsdefdo():cat.turn(180)This will make the cat turn upside down instantly when the program starts.await nyan.sleep(seconds=1)To run code after a waiting period, you can use theawait nyan.sleep()command like this:cat=nyan.new_text('=^.^=')@nyan.when_program_startsasyncdefdo():cat.turn(180)awaitnyan.sleep(seconds=2)cat.turn(180)This will make the cat turn upside down instantly when the program starts, wait 2 seconds, then turn back up again.nyan.broadcast()You can usenyan.broadcast()to broadcast an event that can be picked up by an event listener.@nyan.repeat_foreverdefdo():nyan.broadcast('marco')@nyan.when_event_recieved()To run code in response to a broadcasted event, use@nyan.when_event_recieved(), like this@nyan.when_event_recieved('marco')defdo():print('polo')@nyan.foreach_sprite()attaches a script to each sprite passed or in the case a tag is passed, for each sprite that has the given tag. Should be used in conjunction with@nyan.repeat_foreverand@nyan.when_program_startsdecorators. Example:@nyan.repeat_forever@nyan.foreach_sprite(player1,player2,player3,player4)asyncdefanimate_player(player):next_frame(player)awaitnyan.sleep(player.frameTime)@nyan.repeat_forever@nyan.foreach_sprite(tag='player-missile')asyncdefpropel_missile(missile):missile.move(25)Sprite CommandsSimple commandsSprites (images and text) have a few simple commands:sprite.move(10)— moves the sprite 10 pixels in the direction it's facing (starts facing right). Use negative numbers (-10) to go backward.sprite.move(10, direction=45)— moves the sprite 10 pixels at an angle specified by the direction.sprite.turn(20)— Turns the sprite 20 degrees counter-clockwise. Use negative numbers (-20) to turn the other way.sprite.go_to(other_sprite)— Makesspritejump to another sprite namedother_sprite's position on the screen. Can also be used to make the sprite follow the mouse:sprite.go_to(nyan.mouse).sprite.go_to(x=100, y=50)— Makesspritejump to x=100, y=50 (right and up a little).sprite.point_towards(other_sprite)— Turnsspriteso it points at another sprite calledother_sprite.sprite.point_towards(x=100, y=50)— Turnsspriteso it points toward x=100, y=50 (right and up a little).sprite.hide()— Hidessprite. It can't be clicked when it's hidden.sprite.show()— Showsspriteif it's hidden.sprite.add_tag('car')— Adds a tag namedcarto the sprite. Tagging a sprite adds it to a group that can be fetched later by other functions.sprite.remove_tag('car')— removes thecartag from the spritesprite.clone()— Makes a copy or clone of the sprite and returns it.sprite.remove()— Removes a sprite from the screen permanently. Calling sprite commands on a removed sprite won't do anything.PropertiesSprites also have properties that can be changed to change how the sprite looks. Here they are:sprite.x— The sprite's horizontal position on the screen. Positive numbers are right, negative numbers are left. The default is 0.sprite.y— The sprite's vertical position on the screen. Positive numbers are up, negative numbers are down. The default is 0.sprite.size— How big the sprite is. The default is 100, but it can be made bigger or smaller.sprite.angle— How much the sprite is turned. Positive numbers are counter-clockwise. The default is 0 degrees (pointed to the right).sprite.transparency— How see-through the sprite is from 0 to 100. 0 is completely see-through, 100 is not see-through at all. The default is 100.sprite.brightness- How bright or dim the sprite is from -100 to 100. -100 is completely dark, 100 is white. The default is 0.sprite.is_hidden—Trueif the sprite has been hidden with thesprite.hide()command. OtherwiseFalse.sprite.is_shown—Trueif the sprite has not been hidden with thesprite.hide()command. OtherwiseFalse.sprite.left— The x position of the left-most part of the sprite.sprite.right— The x position of the right-most part of the sprite.sprite.top— The y position of the top-most part of the sprite.sprite.bottom— The y position of the bottom-most part of the sprite.Image-sprite-only properties:sprite.image— The filename of the image shown.Text-sprite-only properties:text.text— The displayed text content.text.font— The filename of the font e.g. 'Arial.ttf'. The default isNone, which will use a built-in font.text.font_size— The text's size. The default is50(pt).text.color— The text's color. The default is black.Box-sprite-only properties:box.color— The color filling the box. The default isblack.box.width— The width of the box. The default is100pixels.box.height— The height of the box. The default is200pixels.box.border_width— The width of the box's border, the line around it. The default is0.box.border_color— The color of the box's border. The default is'light blue'.If the box has a border, the box's total width, including the border, will be the width defined by thewidthproperty.Circle-sprite-only properties:circle.color— The color filling the circle. The default isblack.circle.radius— How big the circle is, measured from the middle to the outside. The default is100pixels, making a 200-pixel-wide circle.circle.border_width— The width of the circle's border, the line around it. The default is0.circle.border_color— The color of the circle's border. The default is'light blue'.If the circle has a border, the circle's total width, including the border, will be the width defined by theradiusproperty.These properties can changed to do the same things as the sprite commands above. For example,sprite.go_to(other_sprite)# the line above is the same as the two lines belowsprite.x=other_sprite.xsprite.y=other_sprite.yYou can change the properties to animate the sprites. The code below makes the cat turn around.cat=nyan.new_text('=^.^=')@nyan.repeat_foreverdefdo():cat.angle+=1# the line above is the same as cat.turn(1)Other infoSprites also have some other useful info:sprite.width— Gets how wide the sprite is in pixels.sprite.height— Gets how tall the sprite is in pixels.sprite.distance_to(other_sprite)— Gets the distance in pixels toother_sprite.sprite.distance_to(x=100, y=100)— Gets the distance to the point x=100, y=100.sprite.is_touching(other_sprite)— Returns True ifspriteis touching theother_sprite. OtherwiseFalse.sprite.is_touching(point)— Returns True if the sprite is touching the point (anything with anxandycoordinate). For example:sprite.is_touching(nyan.mouse)Mouse CommandsWorking with the mouse in Nyan is easy. Here's a simple program that points a sprite at the mouse:arrow=nyan.new_text('-->',font_size=100)@nyan.repeat_foreverdefdo():arrow.point_towards(nyan.mouse)nyan.mousehas the following properties:nyan.mouse.x— The horizontal x position of the mouse.nyan.mouse.y— The vertical y position of the mouse.nyan.mouse.is_clicked—Trueif the mouse is clicked down, orFalseif it's not.nyan.mouse.is_touching(sprite)— ReturnsTrueif the mouse is touching a sprite, orFalseif it's not.@sprite.when_clickedProbably the easiest way to detect clicks is to use@sprite.when_clicked.In the program below, when the face is clicked it changes for 1 second then turns back to normal:face=nyan.new_text('^.^',font_size=100)@face.when_clickedasyncdefdo():face.text='*o*'awaitnyan.sleep(seconds=1)face.text='^.^'@nyan.when_sprite_clicked()If you wanted to run the same code when multiple sprites are clicked, you can use@nyan.when_sprite_clicked():face1=nyan.new_text('^.^',x=-100,font_size=100)face2=nyan.new_text('^_^',x=100,font_size=100)@nyan.when_sprite_clicked(face1,face2)# takes as many sprites as you wantasyncdefdo(sprite):starting_words=sprite.textsprite.text='*o*'awaitplay.sleep(seconds=1)sprite.text=starting_words@nyan.mouse.when_clickedor@nyan.when_mouse_clickedTo run code when the mouse is clicked anywhere, use@nyan.mouse.when_clickedor@nyan.when_mouse_clicked(they do the same exact thing).In the code below, when a click is detected, the text will move to the click location and the coordinates will be shown:text=nyan.new_text('0, 0')@nyan.mouse.when_clickeddefdo():text.text=f'{nyan.mouse.x},{nyan.mouse.y}'text.go_to(nyan.mouse)@nyan.mouse.when_click_releasedor@nyan.when_mouse_click_releasedTo run code when the mouse button is released, use@nyan.mouse.when_click_released@nyan.when_mouse_click_released(they do the same exact thing).In the code below, the cat can be dragged around when it's clicked by the mouse:cat=nyan.new_text('=^.^= drag me!')cat.is_being_dragged=False@cat.when_clickeddefdo():cat.is_being_dragged=True@nyan.mouse.when_click_releaseddefdo():cat.is_being_dragged=False@nyan.repeat_foreverdefdo():ifcat.is_being_dragged:cat.go_to(nyan.mouse)Keyboard Commandsnyan.key_is_pressed()You can usenyan.key_is_pressed()to detect keypresses.In the code below, pressing thearrowkeys orw/a/s/dwill make the cat go in the desired direction.cat=nyan.new_text('=^.^=')@nyan.repeat_foreverdefdo():ifnyan.key_is_pressed('up','w'):cat.y+=15ifnyan.key_is_pressed('down','s'):cat.y-=15ifnyan.key_is_pressed('right','d'):cat.x+=15ifnyan.key_is_pressed('left','a'):cat.x-=15@nyan.when_key_pressed()You can use@nyan.when_key_pressed()to run code when specific keys are pressed.In the code below, pressing thespacekey will change the cat's face, and pressing theenterkey will change it to a different face.cat=nyan.new_text('=^.^=')@nyan.when_key_pressed('space','enter')# if either the space key or enter key are pressed...defdo(key):ifkey=='enter':cat.text='=-.-='ifkey=='space':cat.text='=*_*='@nyan.when_any_key_pressedIf you just want to detect when any key is pressed, you can use@nyan.when_any_key_pressed.In the code below, any key you press will be displayed on the screen:text=nyan.new_text('')@nyan.when_any_key_presseddefdo(key):text.text=f'{key}pressed!'@nyan.when_key_released()Exactly like@nyan.when_key_pressed()but runs the code when specific keys are released.In the code below, text will appear on screen only if theuparrow is pressed.text=nyan.new_text('')@nyan.when_key_released('up')asyncdefdo(key):text.text='up arrow released!'awaitnyan.sleep(seconds=1)text.text=''@nyan.when_any_key_releasedExactly like@nyan.when_any_key_pressedbut runs the code when any key is released.In the code below, the name of the most recently released key will show up on screen.text=nyan.new_text('')@nyan.when_any_key_presseddefdo(key):text.text=f'{key}key released!''Audio Commandsnyan.new_sound()meow=nyan.new_sound(sound='meow.wav')This will load a sound file with.wavextension and makes it ready to be played. This function should be mainly used for sound effects. You can get sounds from online sites likeFreesoundor you can generate your own usingBfxr.meow.play()This will play the loaded sound file.meow=nyan.new_sound(sound='meow.wav')@nyan.when_key_pressed('space')defdo():meow.play()nyan.music.play()To play an mp3 file in the background, usenyan.music.play(), like thisnyan.music.play('William Tell Overture Finale.mp3',loop=True)await nyan.music.play_until_done()This is the same asnyan.music.play(), but waits for the music to finish before continuing@nyan.when_program_startsasyncdefdo():awaitnyan.music.play_until_done('William Tell Overture Finale.mp3')print('music has ended')nyan.music.pause()Pauses the currently playing music@nyan.when_program_startsasyncdefdo():nyan.music.play('William Tell Overture Finale.mp3')awaitnyan.sleep(seconds=5)nyan.music.pause()nyan.music.unpause()Resumes the paused music@nyan.when_program_startsasyncdefdo():nyan.music.play('William Tell Overture Finale.mp3')awaitnyan.sleep(seconds=5)nyan.music.pause()awaitnyan.sleep(seconds=5)nyan.music.unpause()nyan.music.stop()Stops the currently playing music@nyan.when_program_startsasyncdefdo():nyan.music.play('William Tell Overture Finale.mp3')awaitnyan.sleep(seconds=5)nyan.music.stop()nyan.music.volumeYou can usenyan.music.volumeto get or set the current volume which ranges from 0 to 100. The default is 100@nyan.when_program_startsasyncdefdo():nyan.music.play('William Tell Overture Finale.mp3')awaitnyan.sleep(seconds=5)nyan.music.volume=70Other Useful Commandsnyan.screenThe way to get information about the screen.nyan.screenhas these properties:nyan.screen.width- Defaults to 800 (pixels total). Changing this will change the screen's size.nyan.screen.height- Defaults to 600 (pixels total). Changing this will change the screen's size.nyan.screen.left- Thexcoordinate for the left edge of the screen.nyan.screen.right- Thexcoordinate for the right edge of the screen.nyan.screen.top- Theycoordinate for the top of the screen.nyan.screen.bottom- Theycoordinate for the bottom of the screen.nyan.get_sprites()Returns a list of all the sprites (images, shapes, text) in the program. Takes an optional tag parameter that can be used to get all sprites that have a give tag.nyan.random_number()A function that makes random numbers.If two whole numbers are given,nyan.random_number()will give a whole number back:nyan.random_number(lowest=0,highest=100)# example return value: 42(You can also donyan.random_number(0, 100)withoutlowestandhighest.)If non-whole numbers are given, non-whole numbers are given back:nyan.random_number(0,1.0)# example return value: 0.84nyan.random_number()is also inclusive, which meansnyan.random_number(0,1)will return0and1.nyan.random_color()Returns a random RGB color, including white and black.nyan.random_color()# example return value: (201, 17, 142)Each value varies from 0 to 255.nyan.random_position()Returns a random position on the screen. A position object has anxandycomponent.text=nyan.text('WOO')@nyan.repeat_foreverdefdo():text.go_to(nyan.random_position())# the above is equivalent to:position=nyan.random_position()text.x=position.xtext.y=position.ynyan.random_item()Picks a random item from a list. The passed list should contain at least one item.text=nyan.text('WOO')@nyan.repeat_foreverdefdo():random_angle=nyan.random_item([0,90,180,270])text.angle=random_anglenyan.new_timer()Creates a timer. Useful for keeping track of time and for doing animations.timer=new_timer()Once a timer is created, it will have the following commands and properties:timer.reset()— resets the timertimer.seconds— time elapsed in seconds since creation or last resettimer.milliseconds— time elapsed in milliseconds since creation or last resetnyan.clamp()Keeps a number between two values. Useful for constraining a sprite to a limited area.player=nyan.text('>')@nyan.repeat_foreverdefdo():ifnyan.key_is_pressed('right'):player.x+=1ifnyan.key_is_pressed('left'):player.x-=1ifnyan.key_is_pressed('up'):player.y+=1ifnyan.key_is_pressed('down'):player.y-=1player.x=clamp(player.x,-400,400)player.x=clamp(player.y,-300,300)Packaging Nyan ProgramsNyan comes with a packager that can be used to create stand-alone executables that can be shared with other people without them having to install Python on their computers. To use it, run the following in your terminalnyan-packager python_fileThis will create an executable file with other stuff in a dist folder inside your project. You can change the icon of the executable with--icon icon_fileoption. If you would like to have a less cluttered output, you can use--onefileflag to create a single executable + your assets folder.What's with all thisasync/awaitstuff? Is this Python?Yes, this is Python! Python addedasyncandawaitas special keywords in Python 3.7. It's part of theasyncio module.Using async functions means we can use theawait nyan.sleep()function, which makes some code a lot simpler and appear to run in-parallel, which new programmers find intuitive.importnyancat=nyan.new_text('=^.^=')# this code block uses async so it can use the 'await nyan.sleep()' function@nyan.repeat_foreverasyncdefchange_bg():nyan.set_backdrop('pink')awaitnyan.sleep(seconds=1)nyan.set_backdrop('purple')awaitnyan.sleep(seconds=1)nyan.set_backdrop('light blue')awaitnyan.sleep(seconds=1)# this code block doesn't need async because it doesn't have `await nyan.sleep()`@nyan.repeat_foreverdefdo():cat.turn(1)nyan.start_program()In the above program, the backdrop will change and the cat will appear to turn at the same time even though the code is running single-threaded.Theasynckeyword isn't necessary to write unless you want to useawaitfunctions. If you try to use anawaitcommand inside a non-async function, Python will show you an error like this:File "example.py", line 31
    await nyan.sleep(seconds=1)
    ^
SyntaxError: 'await' outside async functionTo fix that error, just putasyncbeforedef.If you don't understand any of this, it's generally safe to just includeasyncbeforedef.