Closing slide menu - android

trying to use slide menu from function https://coronalabs.com/blog/2014/04/08/widgets-creating-a-sliding-panel/
I followed exactly the suggested code and I created a panel with 3 texts and one button. Then I added an event to the button to close the panel, but it does not work. Cannot understand why..:(. Here is the code:
local panel = widget.newPanel
{
location = "left",
--onComplete = panelTransDone,
width = display.contentWidth * 0.8,
height = display.contentHeight * 0.8,
speed = 500,
--inEasing = easing.outBack,
outEasing = easing.outCubic
}
panel.background = display.newRect( 100, -50, 900, 730 )
panel.background:setFillColor( 0.1, 0.1, 0.1, 0.9 )
panel:insert( panel.background )
panel.item1 = display.newText( "GAME DESCRIPTION", 0, 0, native.systemFontBold, 40 )
panel.item1:setFillColor( 1, 1, 0 )
panel.item1.x = -95
panel.item1.y = -350
panel:insert( panel.item1 )
panel.item2 = display.newText( "SET SOUNDS", 0, 0, native.systemFontBold, 40 )
panel.item2:setFillColor( 1, 1, 0 )
panel.item2.x = -170
panel.item2.y = -250
panel:insert( panel.item2 )
panel.item3 = display.newText( "CHECK SCORE", 0, 0, native.systemFontBold, 40 )
panel.item3:setFillColor( 1, 1, 0 )
panel.item3.x = -150
panel.item3.y = -150
panel:insert( panel.item3 )
panel.item4 = display.newText( "CLOSE", 0, 0, native.systemFontBold, 40 )
panel.item4:setFillColor( 1, 1, 0 )
panel.item4.x = -230
panel.item4.y = -50
panel:insert( panel.item4 )
local bottoneex = widget.newButton
{
--defaultFile = "play.png",
label="ESCI",
labelColor =
{
default = { 1, 1, 0, 255 },
},
font = native.systemFont,
fontSize = 40,
emboss = false,
textonly = true,
onEvent = provap
}
bottoneex.x = -250
bottoneex.y = 50
panel:insert( bottoneex )
function apripanel()
panel:show()
panel:toFront()
end
function provap()
panel:hide()
end
My target is to build a slide menu by adding to this panel several menu items. How can I achieve that? I tried putting a button ( textonly = true ) but I am not sure...what if I add displaytext (as I did)? How can I add listeners to texts?
Sorry for silly questions but I am quit new to this language! :)
Thanks a lot for your help! Ubaldo

Hiding the menu works for me, maybe you use an old version of newPanel.lua, this should work for you.
main.lua
widget = require("widget")
require("newPanel")
BG = display.newRect(160,240,300,460)
BG:setFillColor( 0.1, 0.1, 0.1, 1.0 )
local panel = widget.newPanel
{
location = "left",
onComplete = panelTransDone,
width = display.contentWidth*0.8,
height = display.contentHeight,
speed = 500,
inEasing = easing.outBack,
outEasing = easing.outCubic
}
panel.background = display.newRect( 0, 0, 320, 480 )
panel.background:setFillColor( 0.3, 0.3, 0.3, 0.9 )
panel:insert( panel.background )
panel.item1 = display.newText( "Item1", 0, 0, native.systemFontBold, 10 )
panel.item1:setFillColor( 1, 1, 0 )
panel:insert( panel.item1 )
local function ButtonEvent1(e)
if ( "ended" == e.phase ) then
print( "Button 1" )
panel:show()
panel:toFront()
end
end
local function ButtonEvent2(e)
if ( "ended" == e.phase ) then
print( "Button 1" )
panel:hide()
end
end
local B1 = widget.newButton({left = 100,top = 200,id = "button1",label = "Show",onEvent = ButtonEvent1})
local B2 = widget.newButton({left = 100,top = 300,id = "button2",label = "Hide",onEvent = ButtonEvent2})
newPanel.lua
function widget.newPanel( options )
local customOptions = options or {}
local opt = {}
opt.location = customOptions.location or "top"
local default_width, default_height
if ( opt.location == "top" or opt.location == "bottom" ) then
default_width = display.contentWidth
default_height = display.contentHeight * 0.33
else
default_width = display.contentWidth * 0.33
default_height = display.contentHeight
end
opt.width = customOptions.width or default_width
opt.height = customOptions.height or default_height
opt.speed = customOptions.speed or 500
opt.inEasing = customOptions.inEasing or easing.linear
opt.outEasing = customOptions.outEasing or easing.linear
if ( customOptions.onComplete and type(customOptions.onComplete) == "function" ) then
opt.listener = customOptions.onComplete
else
opt.listener = nil
end
local container = display.newContainer( opt.width, opt.height )
if ( opt.location == "left" ) then
container.anchorX = 1.0
container.x = display.screenOriginX
container.anchorY = 0.5
container.y = display.contentCenterY
elseif ( opt.location == "right" ) then
container.anchorX = 0.0
container.x = display.actualContentWidth
container.anchorY = 0.5
container.y = display.contentCenterY
elseif ( opt.location == "top" ) then
container.anchorX = 0.5
container.x = display.contentCenterX
container.anchorY = 1.0
container.y = display.screenOriginY
else
container.anchorX = 0.5
container.x = display.contentCenterX
container.anchorY = 0.0
container.y = display.actualContentHeight
end
function container:show()
local options = {
time = opt.speed,
transition = opt.inEasing
}
if ( opt.listener ) then
options.onComplete = opt.listener
self.completeState = "shown"
end
if ( opt.location == "top" ) then
options.y = display.screenOriginY + opt.height
elseif ( opt.location == "bottom" ) then
options.y = display.actualContentHeight - opt.height
elseif ( opt.location == "left" ) then
options.x = display.screenOriginX + opt.width
else
options.x = display.actualContentWidth - opt.width
end
transition.to( self, options )
end
function container:hide()
local options = {
time = opt.speed,
transition = opt.outEasing
}
if ( opt.listener ) then
options.onComplete = opt.listener
self.completeState = "hidden"
end
if ( opt.location == "top" ) then
options.y = display.screenOriginY
elseif ( opt.location == "bottom" ) then
options.y = display.actualContentHeight
elseif ( opt.location == "left" ) then
options.x = display.screenOriginX
else
options.x = display.actualContentWidth
end
transition.to( self, options )
end
return container
end

Related

My kivy android app does not export its canvas to a file

I am developing a drawing app for android that allows the user to export its canvas to png. I looked on internet on how to do this and it seems that the solution is to use the export_to_png method. On Debian GNU/Linux 11, it works but when I used buildozer to make an android app it doesn't work. My real issue here is that even though I give enough permissions to the app, it simply does not create the png file. Also, I am using PIL to crop the image so the drawing does not include the buttons of the application.
Could anyone tell me how to export a canvas to png in android using kivy?
Could anyone tell me how to crop an image using kivy so I don't have to use PIL?
Could anyone tell me how to export only the canvas so I don't have to crop the image?
By the way, in the export method I used multiple try blocks in order to figure out why my application was crashing each time I tried to export to png. By doing this, I realized that the self.export_to_png("my_plan.png") command was not working. In other words, it does not create the file. I don't think that granting permissions to the app is the problem since the save method creates the data.txt file to save the progress of the user. Also, the load method also works by reading the previously created file. This, however, is not the case for the export method.
Thank you.
This is my main.py code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.widget import Widget
from kivy.graphics import Line
from kivy.graphics import Rectangle
from kivy.graphics import Color
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from PIL import Image
from os import path
class MyRelativeLayout(RelativeLayout):
def __init__(self, **kwargs):
super(MyRelativeLayout, self).__init__(**kwargs)
self.active_tool = "Line"
self.temp_point = [0, 0]
self.dx = 0
self.dy = 0
self.move_factor = 10
self.elements = [Line(points=(0,0), width = 0)]
self.redo_list = []
self.eraser_size = 100
self.eraser = Rectangle(pos = [0, 0], size = [0, 0])
self.more_buttons = RelativeLayout()
self.back_button = Button(text = "Back", pos_hint = {"x": 0, "top": 1}, size_hint = (0.10, 0.10), background_color = (0, 0 ,1, 1))
self.back_button.bind(on_press = self.back)
self.undo_button = Button(text = "Undo", pos_hint = {"x": 0.10, "top": 1}, size_hint = (0.10, 0.10), background_color = (0, 0 ,1, 1))
self.undo_button.bind(on_press = self.undo)
self.redo_button = Button(text = "Redo", pos_hint = {"x": 0.20, "top": 1}, size_hint = (0.10, 0.10), background_color = (0, 0 ,1, 1))
self.redo_button.bind(on_press = self.redo)
self.export_button = Button(text = "Export", pos_hint = {"x": 0.30, "top": 1}, size_hint = (0.10, 0.10), background_color = (0, 0 ,1, 1))
self.export_button.bind(on_press = self.export)
self.more_buttons.add_widget(self.back_button)
self.more_buttons.add_widget(self.undo_button)
self.more_buttons.add_widget(self.redo_button)
self.more_buttons.add_widget(self.export_button)
self.more = Popup(title = "More Buttons", content = self.more_buttons, size_hint = [1, 1])
self.button_size = 100
self.im = None
def on_touch_down(self, touch):
if not(touch.x < self.width * 0.10):
if self.active_tool == "Line":
with self.canvas:
Color(0, 0, 0, 1, mode="rgba")
self.elements.append(Line(points = [touch.x, touch.y], width = 2))
elif self.active_tool == "Rectangle":
with self.canvas:
Color(0, 0, 0, 1, mode="rgba")
self.elements.append(Line(points = [touch.x, touch.y], width = 2))
elif self.active_tool == "Free Hand Drawing":
with self.canvas:
Color(0, 0, 0, 1, mode="rgba")
self.elements.append(Line(points = [touch.x, touch.y], width = 2))
elif self.active_tool == "Eraser":
with self.canvas:
Color(1, 1, 1, 1, mode = "rgba")
self.elements.append(Rectangle(pos = [touch.x - self.eraser_size / 2, touch.y - self.eraser_size / 2], size = [self.eraser_size, self.eraser_size]))
elif self.active_tool == "Move":
self.temp_point = [touch.x, touch.y]
else:
print(self.active_tool + " was not found")
return super(MyRelativeLayout, self).on_touch_down(touch)
def on_touch_move(self, touch):
if not(touch.x < self.width * 0.10):
if self.active_tool == "Line":
self.elements[-1].points = [self.elements[-1].points[0], self.elements[-1].points[1], touch.x, touch.y]
elif self.active_tool == "Rectangle":
self.elements[-1].points = [self.elements[-1].points[0], self.elements[-1].points[1], touch.x, self.elements[-1].points[1], touch.x, touch.y, self.elements[-1].points[0], touch.y, self.elements[-1].points[0], self.elements[-1].points[1]]
elif self.active_tool == "Free Hand Drawing":
self.elements[-1].points += [touch.x, touch.y]
elif self.active_tool == "Eraser":
with self.canvas:
Color(1, 1, 1, 1, mode = "rgba")
self.elements.append(Rectangle(pos = [touch.x - self.eraser_size / 2, touch.y - self.eraser_size / 2], size = [self.eraser_size, self.eraser_size]))
Color(0, 0, 0, 1, mode = "rgba")
elif self.active_tool == "Move":
self.dx = touch.x - self.temp_point[0]
self.dy = touch.y - self.temp_point[1]
with self.canvas:
for i in range(0, len(self.elements)):
if self.get_element(self.elements[i]) == "<class 'kivy.graphics.vertex_instructions.Line'>":
self.canvas.remove(self.elements[i])
self.elements[i] = self.move_line(self.elements[i], self.dx, self.dy)
elif self.get_element(self.elements[i] == "<class 'kivy.graphics.vertex_instructions.Rectangle'>"):
self.canvas.remove(self.elements[i])
Color(1, 1, 1, 1, mode = "rgba")
self.elements[i] = self.move_eraser(self.elements[i], self.dx, self.dy)
Color(0, 0, 0, 1, mode = "rgba")
else:
print(self.active_tool + " was not found")
return super(MyRelativeLayout, self).on_touch_move(touch) # Using super to have the button behavior so we can press the buttons
def on_touch_up(self, touch):
if self.active_tool == "Line":
pass
elif self.active_tool == "Rectangle":
pass
elif self.active_tool == "Free Hand Drawing":
pass
elif self.active_tool == "Eraser":
# with self.canvas:
# self.canvas.remove(self.eraser)
pass
elif self.active_tool == "Move":
self.dx = 0
self.dy = 0
self.temp_point = [0, 0]
else:
print(self.active_tool + " was not found")
def back(self, value):
self.more.dismiss()
def undo(self, value):
# method to undo drawings
if len(self.elements) > 0: # verifying that elements list is not empty
self.canvas.remove(self.elements[-1]) # removing the last drawn element from canvas
self.redo_list.append(self.elements[-1]) # adding the last drawn element to the redo list
self.elements.pop() # deleting the last element in elements list
self.more.dismiss() # closing the popup window
def redo(self, value):
# method to redo drawings
if len(self.redo_list) > 0: # verifying that the redo list is not empty
self.canvas.add(Color(0, 0, 0, 1)) # Changing color to black
self.elements.append(self.redo_list[-1]) # adding the last element in the redo list to the element list
self.canvas.add(self.redo_list[-1]) # adding the last element in the redo list to canvas
self.redo_list.pop() # deleting the last element in redo list
self.more.dismiss()
def export(self, value):
try:
self.export_to_png("my_plan.png")
template = str(path.isfile("my_plan.png"))
popup = Popup(title = "Error", content = Label(text = template))
popup.open()
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
template = str(template.format(type(ex).__name__, ex.args))
popup = Popup(title = "Error", content = Label(text = template))
popup.open()
try:
self.im = Image.open("my_plan.png")
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
template = str(template.format(type(ex).__name__, ex.args))
popup = Popup(title = "Error", content = Label(text = template))
popup.open()
try:
self.im = self.im.crop((int(self.width * 0.10), int(0), int(self.width), int(self.height)))
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
template = str(template.format(type(ex).__name__, ex.args))
popup = Popup(title = "Error", content = Label(text = template))
popup.open()
try:
self.im.save("/storage/emulated/0/my_plan.png")
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
template = str(template.format(type(ex).__name__, ex.args))
popup = Popup(title = "Error", content = Label(text = template))
popup.open()
self.more.dismiss()
def zoom_in(self):
scale_factor = 1.25
with self.canvas:
for i in range(0, len(self.elements)):
if self.get_element(self.elements[i]) == "<class 'kivy.graphics.vertex_instructions.Line'>":
self.canvas.remove(self.elements[i])
self.elements[i] = self.scale_line(self.elements[i], scale_factor)
elif self.get_element(self.elements[i] == "<class 'kivy.graphics.vertex_instructions.Rectangle'>"):
self.canvas.remove(self.elements[i])
Color(1, 1, 1, 1, mode = "rgba")
self.elements[i] = self.scale_eraser(self.elements[i], scale_factor)
Color(0, 0, 0, 1, mode = "rgba")
self.move_factor += 3
self.eraser_size *= 1.25
def zoom_out(self):
scale_factor = 0.75
with self.canvas:
for i in range(0, len(self.elements)):
if self.get_element(self.elements[i]) == "<class 'kivy.graphics.vertex_instructions.Line'>":
self.canvas.remove(self.elements[i])
self.elements[i] = self.scale_line(self.elements[i], scale_factor)
elif self.get_element(self.elements[i] == "<class 'kivy.graphics.vertex_instructions.Rectangle'>"):
self.canvas.remove(self.elements[i])
Color(1, 1, 1, 1, mode = "rgba")
self.elements[i] = self.scale_eraser(self.elements[i], scale_factor)
Color(0, 0, 0, 1, mode = "rgba")
self.move_factor -= 3
self.eraser_size *= 0.75
def move_line(self, line, dx, dy):
new_coordinates = []
for i in range(0, len(line.points)):
if i % 2 == 0:
if dx >= 0 and dy >= 0:
new_coordinates.append(line.points[i] + self.move_factor)
new_coordinates.append(line.points[i+1] + self.move_factor)
elif dx <= 0 and dy >= 0:
new_coordinates.append(line.points[i] - self.move_factor)
new_coordinates.append(line.points[i+1] + self.move_factor)
elif dx >= 0 and dy <= 0:
new_coordinates.append(line.points[i] + self.move_factor)
new_coordinates.append(line.points[i+1] - self.move_factor)
elif dx <= 0 and dy <= 0:
new_coordinates.append(line.points[i] - self.move_factor)
new_coordinates.append(line.points[i+1] - self.move_factor)
else:
print("Unknown direction.")
else:
continue
return Line(points = new_coordinates.copy(), width = 2)
def scale_line(self, line, scale):
new_coordinates = []
for i in range(0, len(line.points)):
new_coordinates.append(line.points[i] * scale)
return Line(points = new_coordinates.copy(), width = 2)
def move_eraser(self, eraser, dx, dy):
if dx >= 0 and dy >= 0:
return Rectangle(pos = [eraser.pos[0] + self.move_factor, eraser.pos[1] + self.move_factor], size = eraser.size)
elif dx <= 0 and dy >= 0:
return Rectangle(pos = [eraser.pos[0] - self.move_factor, eraser.pos[1] + self.move_factor], size = eraser.size)
elif dx >= 0 and dy <= 0:
return Rectangle(pos = [eraser.pos[0] + self.move_factor, eraser.pos[1] - self.move_factor], size = eraser.size)
elif dx <= 0 and dy <= 0:
return Rectangle(pos = [eraser.pos[0] - self.move_factor, eraser.pos[1] - self.move_factor], size = eraser.size)
def scale_eraser(self, eraser, scale):
return Rectangle(pos = [eraser.pos[0] * scale, eraser.pos[1] * scale], size = [eraser.size[0] * scale, eraser.size[1] * scale])
def get_element(self, element):
return str(type(element))
def save_element(self, element):
line = ""
if self.get_element(element) == "<class 'kivy.graphics.vertex_instructions.Line'>":
line += "Line"
for coordinate in element.points:
line += "," + str(coordinate)
elif self.get_element(element) == "<class 'kivy.graphics.vertex_instructions.Rectangle'>":
line += "Rectangle," + str(element.pos[0]) + "," + str(element.pos[1]) + "," + str(element.size[0]) + "," + str(element.size[1])
return line
def save(self):
file = open("data.txt", "w")
data = ""
for element in self.elements:
data += self.save_element(element) + "\n"
file.write(data)
file.close()
def load(self):
for i in range(0, len(self.elements)):
with self.canvas:
self.canvas.remove(self.elements[i])
self.elements = []
try:
file = open("data.txt", "r")
except Exception as ex:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
print(template.format(type(ex).__name__, ex.args))
else:
lines = file.readlines()
tokens = ""
temp_points = []
for line in lines:
tokens = line.split(",")
if tokens[0] == "Line":
for i in range(1, len(tokens)):
temp_points.append(float(tokens[i]))
with self.canvas:
Color(0, 0, 0, 1, mode="rgba")
self.elements.append(Line(points = temp_points, width = 2))
elif tokens[0] == "Rectangle":
with self.canvas:
Color(1, 1, 1, 1, mode="rgba")
self.elements.append(Rectangle(pos = [float(tokens[1]), float(tokens[2])], size = [float(tokens[3]), float(tokens[4])]))
Color(0, 0, 0, 1, mode="rgba")
temp_points = []
file.close()
def change_active_tool_line(self):
self.active_tool = "Line"
def change_active_tool_rectangle(self):
self.active_tool = "Rectangle"
def change_active_tool_free_hand_drawing(self):
self.active_tool = "Free Hand Drawing"
def change_active_tool_eraser(self):
self.active_tool = "Eraser"
def change_active_tool_move(self):
self.active_tool = "Move"
class MyPlanApp(App):
def build(self):
return MyRelativeLayout()
MyPlanApp().run()
This is my myplan.kv file code
<MyRelativeLayout>:
RelativeLayout:
id: drawing_area
size_hint: 0.90, 1
pos_hint: {"x": 0.10, "y": 0}
canvas:
Color:
rgb: 1, 1, 1
Rectangle:
group: "white_background"
size: self.size
Color:
rgb: 1, 0, 0
RelativeLayout:
size_hint: 0.10, 1
pos_hint: {"x": 0, "top": 1}
Button:
text: "Hand"
pos_hint: {"x": 0, "top": 1}
size_hint: 1, 0.10
background_color: 0, 0, 1, 1
on_press: root.change_active_tool_free_hand_drawing()
Button:
text: "Line"
pos_hint: {"x": 0, "top": 0.90}
size_hint: 1, 0.10
background_color: 0, 0, 1, 1
on_press: root.change_active_tool_line()
Button:
text: "Rectangle"
pos_hint: {"x": 0, "top": 0.80}
size_hint: 1, 0.10
background_color: 0, 0, 1, 1
on_press: root.change_active_tool_rectangle()
Button:
text: "Eraser"
pos_hint: {"x": 0, "top": 0.70}
size_hint: 1, 0.10
background_color: 0, 0, 1, 1
on_press: root.change_active_tool_eraser()
Button:
text: "Zoom in"
pos_hint: {"x": 0, "top": 0.60}
size_hint: 1, 0.10
background_color: 0, 0, 1, 1
on_press: root.zoom_in()
Button:
text: "Zoom out"
pos_hint: {"x": 0, "top": 0.50}
size_hint: 1, 0.10
background_color: 0, 0, 1, 1
on_press: root.zoom_out()
Button:
text: "Move"
pos_hint: {"x": 0, "top": 0.40}
size_hint: 1, 0.10
background_color: 0, 0, 1, 1
on_press: root.change_active_tool_move()
Button:
text: "Save"
pos_hint: {"x": 0, "top": 0.30}
size_hint: 1, 0.10
background_color: 0, 0, 1, 1
on_press: root.save()
Button:
text: "Load"
pos_hint: {"x": 0, "top": 0.20}
size_hint: 1, 0.10
background_color: 0, 0, 1, 1
on_press: root.load()
Button:
text: "More"
pos_hint: {"x": 0, "top": 0.10}
size_hint: 1, 0.10
background_color: 0, 0, 1, 1
on_press: root.more.open()
I also included PIL in my buildozer.spec file.

attempt to call method 'applyForce'

I'm making a side scroller and when i start my game i can touch the screen to keep my penguin in the air, but when i fail and collide with an ice block and press play after going to restart.lua i get the error attempt to call method 'applyForce'
heres my code
local function activatePengs(self,event)
self:applyForce(0, -45, self.x, self.y)
print("run")
end
local function touchScreen(event)
print("touch")
if event.phase == "began" then
peng.enterFrame = activatePengs
Runtime:addEventListener("enterFrame", peng)
end
if event.phase == "ended" then
Runtime:removeEventListener("enterFrame", peng)
end
end
local function onCollision(event)
if event.phase == "began" then
print "collide"
composer.gotoScene( "restart",{ time=800, effect="crossFade" } )
end
end
-- now comes four required functions for Composer:
function scene:create( event )
local sceneGroup = self.view
bg1 = display.newImageRect(sceneGroup, "bg.png", 800, 1000)
bg2 = display.newImage(sceneGroup, "ice2.png",140,210)
bg3 = display.newImage(sceneGroup, "ice2.png",540,210)
bg4 = display.newImage(sceneGroup, "ice2.png",940,210)
bg5 = display.newImage(sceneGroup, "ice2.png",1340,210)
bg6 = display.newImage(sceneGroup, "ice2.png",1740,210)
bg7 = display.newImage(sceneGroup, "ice1.png",140,420)
bg8 = display.newImage(sceneGroup, "ice1.png",540,420)
bg9 = display.newImage(sceneGroup, "ice1.png",940,420)
bg10 = display.newImage(sceneGroup, "ice1.png",1340,420)
bg11 = display.newImage(sceneGroup, "ice1.png",1740,420)
peng = display.newImage(sceneGroup, "peng.png", 80, 201)
physics.addBody(peng, "dynamic", {density=.18, bounce=0.1, friction=.5, radius=55})
...
end
Probably the error occurs because penguin is not a physics object when the function is called. I think remove enterFrame listener before go to next scene should solve your problem.
I added some improvements to your code (not tested) :
local applyForceToPenguin = false
local function enterFrame( self, event )
if applyForceToPenguin then
self:applyForce( 0, -45, self.x, self.y )
print("run")
end
end
local function touchScreen(event)
print("touch")
if event.phase == "began" then applyForceToPenguin = true end
if event.phase == "ended" then applyForceToPenguin = false end
end
local function onCollision(event)
if event.phase == "began" then
print "collide"
applyForceToPenguin = false
composer.gotoScene( "restart",{ time=800, effect="crossFade" } )
end
end
-- now comes four required functions for Composer:
function scene:create( event )
local sceneGroup = self.view
bg1 = display.newImageRect( sceneGroup, "bg.png", 800, 1000 )
bg2 = display.newImage( sceneGroup, "ice2.png", 140, 210 )
bg3 = display.newImage( sceneGroup, "ice2.png", 540, 210 )
bg4 = display.newImage( sceneGroup, "ice2.png", 940, 210 )
bg5 = display.newImage( sceneGroup, "ice2.png", 1340, 210 )
bg6 = display.newImage( sceneGroup, "ice2.png", 1740, 210 )
bg7 = display.newImage( sceneGroup, "ice1.png", 140, 420 )
bg8 = display.newImage( sceneGroup, "ice1.png", 540, 420 )
bg9 = display.newImage( sceneGroup, "ice1.png", 940, 420 )
bg10 = display.newImage( sceneGroup, "ice1.png", 1340, 420 )
bg11 = display.newImage( sceneGroup, "ice1.png", 1740, 420 )
peng = display.newImage( sceneGroup, "peng.png", 80, 201)
physics.addBody( peng, "dynamic", { density=.18, bounce=0.1, friction=.5, radius=55 } )
Runtime:addEventListener( "enterFrame", enterFrame )
...
end
function scene:destroy()
Runtime:removeEventListener( "enterFrame", enterFrame )
end
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if phase == "will" then
-- Code here runs when the scene is still off screen (but is about to come on screen)
elseif phase == "did" then
-- Code here runs when the scene is entirely on screen
applyForceToPenguin = false
end
end
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
Have a nice day:)

Android PhotoView Keep Zoom After Orientation Change

I am utilizing the PhotoView class by Chris Banes to be able to zoom into an image and see it, but I want to make it so that when I change the orientation, the photo will still be zoomed in after the change.
I understand the basics of how to do this, that when an orientation change is detected, onSaveInstanceState will be called, so I'm trying to save the instance in there, and then put it back into the PhotoView when onCreate is called.
public class MainActivity extends ActionBarActivity
{
PhotoView mPhotoView;
#Override
protected void onCreate( Bundle aSavedInstanceState )
{
super.onCreate( aSavedInstanceState );
mPhotoView = new PhotoView(this);
mPhotoView.setMaximumScale( 12 );
setContentView( mPhotoView );
mPhotoView.setImageResource( R.drawable.vm_app_icon);
if (aSavedInstanceState != null)
{
RectF theRect = aSavedInstanceState.getParcelable( "Rect" );
if ( theRect != null)
{
Matrix theMatrix = new Matrix();
theMatrix.setScale( theRect.bottom, theRect.left, theRect.right, theRect.top );
mPhotoView.setDisplayMatrix( theMatrix );
}
}
}
#Override
protected void onSaveInstanceState( final Bundle outState )
{
super.onSaveInstanceState( outState );
RectF theRect = mPhotoView.getDisplayRect();
if (theRect != null)
{
outState.putParcelable( "Rect", theRect );
}
}
}
But this doesn't work. What should I be storing in the bundle to be able to apply back to the PhotoView to keep the zoom level?
Alright after like 10 hours of trying I've figured it out.
To save the zoom level I needed to save two things in the Bundle, the Scale (Zoom level), and the DisplayRect (of type RectF).
Zoom Level - Number between the MinScale and MaxScale, in my instance between 1 and 16
The RectF holds four values, which for some reason are the coordinates of the Top-Left corner of the current view with respect to the current screen orientation. Even though it holds the top-left coordinates I don't want to rotate around that, I want to rotate around the center, so I need to find the center of the rect and then divide that value by the "ScreenBase" which is a value that will standardize the values and will make it able to be translated into a difference plane. Here's how I saved it:
#Override
protected void onSaveInstanceState( final Bundle outState )
{
super.onSaveInstanceState( outState );
Matrix theMatrix = mPhotoView.getDisplayMatrix();
float[] theFloat = new float[9];
theMatrix.getValues( theFloat );
RectF theRect = mPhotoView.getDisplayRect();
if (theRect != null)
{
if( theRect.left > ( mViewWidth / 2 ) || ( theRect.left >= 0 ) )
{
theRect.left = 0;
}
else
{
theRect.left = ( theRect.left - ( mViewWidth / 2 ) ) / mScreenBase;
}
if( theRect.top > ( mViewHeight / 2 ) || ( theRect.top >= 0 ) )
{
theRect.top = 0;
}
else
{
theRect.top = ( theRect.top - ( mViewHeight / 2 ) ) / mScreenBase;
}
outState.putParcelable( "RectF", theRect );
outState.putFloat( "ZoomLevel", mPhotoView.getScale() );
}
}
Then when we pick it up on the other side, we have to do a lot of manipulation to the numbers to get the top left corner of the new screen space centered around the same place (and manipulate it if an boundary problem occurs), here's how I did it:
#Override
protected void onCreate( final Bundle aSavedInstanceState )
{
super.onCreate( aSavedInstanceState );
mPhotoView = new PhotoView( this );
mPhotoView.setMaximumScale( 16 );
setContentView( mPhotoView );
mPhotoView.setImageResource( R.drawable.vm_app_icon );
mPhotoView.getViewTreeObserver().addOnPreDrawListener( new ViewTreeObserver.OnPreDrawListener()
{
public boolean onPreDraw()
{
mPhotoView.getViewTreeObserver().removeOnPreDrawListener( this );
mViewHeight = mPhotoView.getMeasuredHeight();
mViewWidth = mPhotoView.getMeasuredWidth();
Matrix theMatrix = mPhotoView.getDisplayMatrix();
theMatrix.getValues( mBaseMatrixValues );
mScreenBase = mBaseMatrixValues[ 0 ];
int theWidth = mPhotoView.getWidth();
Log.e(TAG, theWidth + "");
if( aSavedInstanceState != null )
{
float[] theFloats = new float[ 9 ];
float theZoom = aSavedInstanceState.getFloat( "ZoomLevel" );
RectF theRect = aSavedInstanceState.getParcelable( "RectF" );
theFloats[ 0 ] = theZoom;
theFloats[ 4 ] = theZoom;
theFloats[ 2 ] = ( theRect.left * mScreenBase ) - ( theZoom * mBaseMatrixValues[ 2 ] ) + ( mViewWidth / 2 ); //Left
theFloats[ 5 ] = ( theRect.top * mScreenBase ) - ( theZoom * mBaseMatrixValues[ 5 ] ) + ( mViewHeight / 2 ); //Top
theFloats[ 8 ] = (float) 1.0;
theFloats = CheckBoundaries( theZoom, theFloats, theRect );
theMatrix.setValues( theFloats );
mPhotoView.setDisplayMatrix( theMatrix ); //Sets the mSuppMatrix in the PhotoViewAttacher
Matrix theImageViewMatrix = mPhotoView.getDisplayMatrix(); //Gets the new mDrawMatrix
mPhotoView.setImageMatrix( theImageViewMatrix ); //And applies it to the PhotoView (catches out of boundaries problems)
}
return true;
}
} );
}
private float[] CheckBoundaries(final float aZoom, float[] aFloats, final RectF aRect )
{
if( aZoom == 1.0 ) //If the zoom is all the way out
{
aFloats[ 2 ] = 0;
aFloats[ 5 ] = 0;
return aFloats;
}
theMaxLeftValue = ( ( mViewHeight * aZoom ) - mViewWidth + ( aZoom * mBaseMatrixValues[ 2 ] ) );
theMaxTopValue = ( ( mViewWidth * aZoom ) - mViewHeight + ( aZoom * mBaseMatrixValues[ 5 ] ) );
if( Math.abs( aFloats[ 2 ] ) > ( theMaxLeftValue ) )
{
aFloats[ 2 ] = -Math.abs( theMaxLeftValue ) + 10;
}
else if( Math.abs( aFloats[ 2 ] ) < ( aZoom * mBaseMatrixValues[ 2 ] ) )
{
aFloats[ 2 ] = -( aZoom * mBaseMatrixValues[ 2 ] );
}
if( Math.abs( aFloats[ 5 ] ) > ( theMaxTopValue ) )
{
aFloats[ 5 ] = -Math.abs( theMaxTopValue ) + 10;
}
else if( Math.abs( aFloats[ 5 ] ) < ( aZoom * mBaseMatrixValues[ 5 ] ) )
{
aFloats[ 5 ] = -( aZoom * mBaseMatrixValues[ 5 ] );
}
if( aFloats[ 2 ] > 0 )
aFloats[ 2 ] = -( mViewWidth / 2 );
else if( aFloats[ 5 ] > 0 )
aFloats[ 5 ] = -( mViewHeight / 2 );
return aFloats;
}

Stop physics for single object in Corona SDK?

I'm having a problem when I try to restart my game. I pause the physics, then when the user clicks the button, the physics are supposed to restart. When I put in physics.start(), though the game crashes. So, I was wondering if it's possible to pause one physical object and then change it's position on the screen. I'm kind of a newb so any answer will be helpful.
local physics = require( "physics")
physics.start( )
local crate1 = display.newRect( display.contentWidth/2,display.contentHeight/2, 40,40)
physics.addBody( crate1, { density=4.0, friction=0.3, bounce=.4} )
crate1.bodyType = "dynamic"
crate1.isBodyActive = true
crate1:setFillColor( 1,0,.3)
sky = display.newRect( display.contentWidth/2, .5, display.contentWidth, 0.000000000000000000001)
physics.addBody( sky, {density=4.0, friction=0.3, bounce=1.5} )
sky.bodyType = "static"
ground = display.newRect( display.contentWidth/2, display.contentHeight, display.contentWidth, .00000000001 )
physics.addBody( ground, {density=4.0, friction=0.3, bounce=1.5 } )
ground.bodyType = "static"
rightWall = display.newRect( display.contentWidth, display.contentHeight/2, 1, display.contentHeight )
physics.addBody( rightWall, {density=4.0, friction=0.3, bounce=1.5} )
rightWall.bodyType = "static"
leftWall = display.newRect(1, display.contentHeight/2, .0000000001, display.contentHeight )
physics.addBody( leftWall, {density=4.0, friction=0.3, bounce=1.5} )
leftWall.bodyType = "static"
physics.setGravity( 0, 3 )
local function handleCollisionOnDelay( event )
local obj = event.source.object
obj.isBodyActive = false
end
local function onLocalCollision( self, event )
if ( event.phase == "began" ) then
local dr = timer.performWithDelay( 10, handleCollisionOnDelay )
dr.object = self
crate1.x = display.contentWidth/2
crate1.y = display.contentHeight/2
end
end
crate1.collision = onLocalCollision
crate1:addEventListener( "collision", crate1 )
use isBodyActive property
http://docs.coronalabs.com/api/type/Body/isBodyActive.html
good luck

three.js - webgl and canvas rendering performance issue

I've created a 3d scene with below code.
<!DOCTYPE html>
<html lang="en">
<head>
<title>3d Model using HTML5 and three.js</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="three.min.js" type="text/javascript"></script>
<script src="Curve.js" type="text/javascript"></script>
<script src="TubeGeometry.js" type="text/javascript"></script>
<script src="Stats.js" type="text/javascript"></script>
<script src="Detector.js" type="text/javascript"></script>
<script>
// variables
var container, stats;
var camera, scene, renderer, splineCamera, cameraHelper, cameraEye;
var text, plane, tube, tubeMesh, parent;
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var mouseX = 0;
var mouseXOnMouseDown = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var binormal = new THREE.Vector3();
var normal = new THREE.Vector3();
init();
animate();
function init(){
// container
container = document.createElement( 'div' );
document.body.appendChild( container );
// info div
info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
//info.innerHTML = 'Drag to spin the cylinder<br/> You can identify cylinder face by clicking on it.</br>';
container.appendChild( info );
// camera
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set(30,10,10);
//camera.up = new THREE.Vector3( 0, 1, 1 );
// scene
scene = new THREE.Scene();
camera.lookAt(scene.position);
// light
scene.add( new THREE.AmbientLight( 0x404040 ) );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 1, 0 );
scene.add( light );
// CONTROLS
controls = new THREE.TrackballControls( camera );
// Grid
geometry = new THREE.Geometry();
geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) );
geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) );
for ( var i = 0; i <= 20; i ++ ) {
line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
line.position.z = ( i * 50 ) - 500;
scene.add( line );
line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );
line.position.x = ( i * 50 ) - 500;
line.rotation.y = 90 * Math.PI / 180;
scene.add( line );
}
// extrudePath, Helix Curve
extrudePath = new THREE.SplineCurve3([
new THREE.Vector3(0, 10, 10),
new THREE.Vector3(10, 0, 10),
new THREE.Vector3(10, 0, 0)
]);
console.log(extrudePath);
// Tube Geometry
var segments = 50;
var closed = false;
var debug = true;
var radiusSegments = 12;
//alert('hello');
var tube = new THREE.TubeGeometry(extrudePath, segments, 2, radiusSegments, closed, debug);
// Tube Mesh
tubeMesh = THREE.SceneUtils.createMultiMaterialObject( tube, [
new THREE.MeshLambertMaterial({
color: 0xff00ff,
opacity: tube.debug ? 0.2 : 0.8,
transparent: true
}),
new THREE.MeshBasicMaterial({
color: 0x000000,
opacity: 0.5,
wireframe: true
})]);
parent = new THREE.Object3D();
parent.position.y = 100;
if ( tube.debug ) tubeMesh.add( tube.debug );
//parent.add( tubeMesh );
scene.add( tubeMesh );
// projector
projector = new THREE.Projector();
// renderer
//renderer = new THREE.CanvasRenderer();
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
// stats
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
document.addEventListener( 'mousedown', onDocumentMouseDown, false );
document.addEventListener( 'mouseover', onDocumentMouseOver, false );
document.addEventListener( 'touchstart', onDocumentTouchStart, false );
document.addEventListener( 'touchmove', onDocumentTouchMove, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.left = window.innerWidth / - 2;
camera.right = window.innerWidth / 2;
camera.top = window.innerHeight / 2;
camera.bottom = window.innerHeight / - 2;
camera.aspect = window.innerWidth / window.innerHeight;
//camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseDown( event ) {
event.preventDefault();
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mouseout', onDocumentMouseOut, false );
mouseXOnMouseDown = event.clientX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
function onDocumentMouseMove( event ) {
mouseX = event.clientX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
}
function onDocumentMouseUp( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentMouseOut( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentMouseOver( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentTouchStart( event ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
}
function onDocumentTouchMove( event ) {
if ( event.touches.length === 1 ) {
event.preventDefault();
mouseX = event.touches[ 0 ].pageX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
}
}
function animate() {
requestAnimationFrame( animate );
render();
update();
}
function update()
{
controls.update();
stats.update();
}
function render() {
tubeMesh.rotation.y += ( targetRotation - tubeMesh.rotation.y ) * 0.15;
camera.updateMatrixWorld();
renderer.render( scene, camera );
}
</script>
</body>
</html>
Now when I change rendering from WebGL to Canvas, the FPS drops down to 1-2 FPS from 56-57 FPS on mobile browser. Native browser does not display anything on page and in Opera page becomes too slow for operations. How do I make page operations fast with Canvas rendering or how do I enable webgl rendering on mobile browsers ?
canvas renderer is software mode only, that means no GPU acceleration, the CPU has to do all the hard work that's why your fps drop.
AFAIK not every mobile browser is able to use webgl renderer yet, you could give opera mobile a try it's capable of webgl.
One way to speed up canvas rendering is to reduce the number of segments used in TubeGeometry

Categories

Resources