add 3 example plasmoids to be ported

and a TODO file to keep track
This commit is contained in:
Marco Martin 2013-09-04 11:42:40 +02:00
parent ea2af90699
commit 93db6ee7b0
39 changed files with 1304 additions and 0 deletions

8
examples/TODO Normal file
View File

@ -0,0 +1,8 @@
Still to be ported
Applets:
* nowplaying
* pairsgame
* samegame

View File

@ -0,0 +1,135 @@
/*
* Copyright 2010 Marco Martin <notmart@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import Qt 4.7
import org.kde.plasma.graphicswidgets 0.1 as PlasmaWidgets
import org.kde.plasma.core 0.1 as PlasmaCore
import org.kde.plasma.graphicslayouts 4.7 as GraphicsLayouts
QGraphicsWidget {
id: page;
preferredSize: "200x200"
minimumSize: "200x20"
property string activeSource: ''
Item {
id:main
PlasmaCore.DataSource {
id: dataSource
dataEngine: "nowplaying"
connectedSources: ['players']
interval: 500
onNewData: {
if (sourceName == 'players') {
print("going to connect to " + data['players'][0])
activeSource = data['players'][0]
connectedSources = ['players', activeSource]
}
}
onDataChanged: {
if (!activeSource) {
return;
}
if (data[activeSource].State == "playing") {
playPause.setIcon("media-playback-pause")
} else {
playPause.setIcon("media-playback-start")
}
progress.value = 100*data[activeSource].Position/data[activeSource].Length
}
}
PlasmaCore.Theme {
id: theme
}
}
Component.onCompleted:
{
dataSource.serviceForSource(activeSource).associateWidget(stop, "stop");
dataSource.serviceForSource(activeSource).associateWidget(progress, "progress");
}
layout: GraphicsLayouts.QGraphicsLinearLayout {
PlasmaWidgets.IconWidget {
id: playPause
property string state: "stop"
onClicked: {
var operation;
if (dataSource.data[activeSource].State == "playing") {
operation = "pause"
} else {
operation = "play"
}
var data = dataSource.serviceForSource(activeSource).operationDescription(operation);
print(dataSource.serviceForSource(activeSource).name);
for ( var i in data ) {
print(i + ' -> ' + data[i] );
}
dataSource.serviceForSource(activeSource).startOperationCall(dataSource.serviceForSource(activeSource).operationDescription(operation));
print("stopping");
}
}
PlasmaWidgets.IconWidget {
id: stop
Component.onCompleted: {
setIcon("media-playback-stop");
}
onClicked: {
var data = dataSource.serviceForSource(activeSource).operationDescription("stop");
print(dataSource.serviceForSource(activeSource).name);
for ( var i in data ) {
print(i + ' -> ' + data[i] );
}
dataSource.serviceForSource(activeSource).startOperationCall(dataSource.serviceForSource(activeSource).operationDescription("stop"));
print("stopping");
}
}
PlasmaWidgets.Slider {
id: progress
orientation: Qt.Horizontal
onSliderMoved: {
var operation = dataSource.serviceForSource(activeSource).operationDescription("seek");
operation.seconds = Math.round(dataSource.data[activeSource].Length*(value/100));
for ( var i in operation ) {
print(i + ' -> ' + operation[i] );
}
dataSource.serviceForSource(activeSource).startOperationCall(operation);
print("set progress to " + progress);
}
}
}
}

View File

@ -0,0 +1,32 @@
[Desktop Entry]
Name=Now playing (QML)
Name[ja]= (QML)
Name[km]= (QML)
Name[nds]=Lopen Stück (QML)
Name[pt]=Agora a tocar (QML)
Name[pt_BR]=Reproduzindo agora (QML)
Name[sv]=Spelar nu (QML)
Name[uk]=Зараз відтворюється (QML)
Name[x-test]=xxNow playing (QML)xx
Comment=A proof of concept media player controller qml
Comment[km]= qml
Comment[pt]=Uma prova de conceito de um controlador multimédia em QML
Comment[pt_BR]=Uma prova de conceito de um controlador multimídia em QML
Comment[sv]=Ett koncept för ett kontrollverktyg för mediaspelare i QML
Comment[uk]=Тестова програма для спостереження за відтворенням мультимедійних даних, написана мовою qml
Comment[x-test]=xxA proof of concept media player controller qmlxx
Encoding=UTF-8
Icon=applications-multimedia
ServiceTypes=Plasma/Applet
Type=Service
X-KDE-PluginInfo-Author=Marco Martin
X-KDE-PluginInfo-Category=Examples
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-Email=notmart@gmail.com
X-KDE-PluginInfo-EnabledByDefault=true
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-Name=org.kde.nowplaying-qml
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=http://plasma.kde.org/
X-Plasma-API=declarativeappletscript
X-Plasma-MainScript=qml/main.qml

View File

@ -0,0 +1,138 @@
/***************************************************************************
* Copyright 2010 by Davide Bettio <davide.bettio@kdemail.net> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 1.0
Flipable {
id: card;
property string cardPicture: "card.svgz";
property bool showPicture: false;
property bool matched: false;
state: "normal"
width: cardBack.width
height: cardBack.height
Behavior on opacity {
NumberAnimation {
target: card
property: "opacity"
duration: 300
}
}
front: Image {
id: cardBack
anchors.centerIn: parent
source: "card.svgz";
}
back: Image {
anchors.centerIn: parent
source: cardPicture;
}
transform: Rotation {
id: rotation
origin.x: card.width/2
origin.y: card.height/2
axis.x: 0; axis.y: 1; axis.z: 0
angle: 0
Behavior on angle {
NumberAnimation {
target: rotation
property: "angle"
duration: 300
}
}
}
SequentialAnimation {
id: checkAnimation
NumberAnimation {
target: rotation
property: "angle"
duration: 300
from: 0
to: 180
}
PauseAnimation {
duration: 300
}
NumberAnimation {
target: rotation
property: "angle"
duration: 300
from: 180
to: 0
}
}
MouseArea {
id: mouseArea;
anchors.fill: parent;
onClicked: {
if (!pairsCanvas.currentCard){
pairsCanvas.currentCard = card;
card.state = "checking"
} else if (pairsCanvas.currentCard != card) {
if (pairsCanvas.currentCard.cardPicture == card.cardPicture){
card.state = pairsCanvas.currentCard.state = "matched"
pairsCanvas.matchesCountdown--;
} else {
card.state = pairsCanvas.currentCard.state = "normal"
checkAnimation.running = true
}
pairsCanvas.currentCard = null;
}
}
}
states: [
State {
name: "normal";
PropertyChanges {
target: card;
showPicture: false
}
PropertyChanges {
target: rotation;
angle: 0
}
},
State {
name: "checking";
PropertyChanges {
target: rotation;
angle: 180
}
},
State {
name: "matched";
PropertyChanges {
target: card;
opacity: 0.3
enabled: false
showPicture: true
}
PropertyChanges {
target: rotation;
angle: 180
}
}
]
}

View File

@ -0,0 +1,49 @@
/***************************************************************************
* Copyright 2010 by Marco Martin <mart@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 1.0
Rectangle {
id:main
property int time: 0
property bool running: true
color: Qt.rgba(1,1,1,0.7)
radius: 10
smooth: true
width: childrenRect.width + 20
height: childrenRect.height + 20
Text {
anchors.horizontalCenter: parent.horizontalCenter
x: 10
y: 10
text: ""+Math.floor((time/60)/10)+Math.floor((time/60))+":"+Math.floor((time%60)/10)+(time%60)%10
font.pointSize: 22
}
Timer {
interval: 1000
running: main.running
repeat: true
onTriggered: {
time++
}
}
}

View File

@ -0,0 +1,49 @@
/***************************************************************************
* Copyright 2010 by Marco Martin <mart@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 1.0
Rectangle {
id:main
property int time: 0
property bool running: true
color: Qt.rgba(1,1,1,0.7)
radius: 10
smooth: true
width: childrenRect.width + 20
height: childrenRect.height + 20
Text {
x: 10
y: 10
text: "WIN!!!"
font.pointSize: 52
}
Behavior on y {
NumberAnimation {
target: main
property: "y"
duration: 1000
easing.type: "OutBounce"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,50 @@
/***************************************************************************
* Copyright 2010 by Davide Bettio <davide.bettio@kdemail.net> *
* Copyright 2010 by Marco Martin <mart@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
var rows = 3
var columns = 4
var maxVal = rows*columns
var elementsGrid = new Array(rows)
for (var i=0; i < rows; ++i) {
elementsGrid[i] = new Array(columns)
}
function init()
{
gameTimer.running = true
gameTimer.time = 0
winMessage.y = -winMessage.height
matchesCountdown = rows*columns / 2;
var pairs = new Array("bug", "bug", "clock", "clock", "kde", "kde", "konqueror", "konqueror", "magicwand", "magicwand", "plasma", "plasma")
elements.clear();
var remaining = maxVal
for (var i=0; i < maxVal; ++i) {
var randVal = Math.round((Math.random()*remaining-1))
var element = pairs.splice(randVal, 1)
--remaining
elements.append({"card": String(element)})
elementsGrid[Math.floor(i/columns)][columns%i] = element
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,82 @@
/***************************************************************************
* Copyright 2010 by Davide Bettio <davide.bettio@kdemail.net> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
***************************************************************************/
import QtQuick 1.0
import "gamelogic.js" as GameLogic
Image {
id: pairsCanvas;
width: 800;
height: 480;
source: "background.jpg"
property Item currentCard;
property int matchesCountdown;
onMatchesCountdownChanged: {
if (matchesCountdown == 0) {
gameTimer.running = false
winMessage.y = pairsCanvas.height/2 - winMessage.height/2
}
}
Column {
Image {
source: "cards-reset.png"
MouseArea {
anchors.fill: parent;
onClicked: GameLogic.init();
}
}
GameTimer {
id: gameTimer
width: parent.width
}
}
ListModel {
id: elements
Component.onCompleted: {
GameLogic.init()
}
}
Grid {
id: mainGrid
anchors.fill: parent
rows: GameLogic.rows
columns: GameLogic.columns
spacing: 5
Repeater {
id: repeater
model: elements
delegate: Card {
cardPicture: card+"-card.png"
}
}
}
WinMessage {
id: winMessage
anchors.horizontalCenter: mainGrid.horizontalCenter
y: -height
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,2 @@
[Dolphin]
Timestamp=2010,8,30,14,12,1

View File

@ -0,0 +1,109 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
import Qt 4.7
import Qt.labs.particles 1.0
Item {
id: block
property bool dying: false
property bool spawned: false
property int type: 0
Behavior on x {
enabled: spawned;
SpringAnimation{ spring: 2; damping: 0.2 }
}
Behavior on y {
SpringAnimation{ spring: 2; damping: 0.2 }
}
Image {
id: img
source: {
if(type == 0){
"pics/redStone.png";
} else if(type == 1) {
"pics/blueStone.png";
} else {
"pics/greenStone.png";
}
}
opacity: 0
Behavior on opacity { NumberAnimation { duration: 200 } }
anchors.fill: parent
}
Particles {
id: particles
width: 1; height: 1
anchors.centerIn: parent
emissionRate: 0
lifeSpan: 700; lifeSpanDeviation: 600
angle: 0; angleDeviation: 360;
velocity: 100; velocityDeviation: 30
source: {
if(type == 0){
"pics/redStar.png";
} else if (type == 1) {
"pics/blueStar.png";
} else {
"pics/greenStar.png";
}
}
}
states: [
State {
name: "AliveState"; when: spawned == true && dying == false
PropertyChanges { target: img; opacity: 1 }
},
State {
name: "DeathState"; when: dying == true
StateChangeScript { script: particles.burst(50); }
PropertyChanges { target: img; opacity: 0 }
StateChangeScript { script: block.destroy(1000); }
}
]
}

View File

@ -0,0 +1,75 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
import Qt 4.7
Rectangle {
id: container
property string text: "Button"
signal clicked
width: buttonLabel.width + 20; height: buttonLabel.height + 6
smooth: true
border { width: 1; color: Qt.darker(activePalette.button) }
radius: 8
color: activePalette.button
gradient: Gradient {
GradientStop {
position: 0.0
color: {
if (mouseArea.pressed)
return activePalette.dark
else
return activePalette.light
}
}
GradientStop { position: 1.0; color: activePalette.button }
}
MouseArea { id: mouseArea; anchors.fill: parent; onClicked: container.clicked() }
Text {
id: buttonLabel; text: container.text; anchors.centerIn: container; color: activePalette.buttonText
}
}

View File

@ -0,0 +1,77 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
import Qt 4.7
Rectangle {
id: page
property Item text: dialogText
signal closed
signal opened
function forceClose() {
if(page.opacity == 0)
return; //already closed
page.closed();
page.opacity = 0;
}
function show(txt) {
page.opened();
dialogText.text = txt;
page.opacity = 1;
}
width: dialogText.width + 20; height: dialogText.height + 20
color: "white"
border.width: 1
opacity: 0
visible: opacity > 0
Behavior on opacity {
NumberAnimation { duration: 1000 }
}
Text { id: dialogText; anchors.centerIn: parent; text: "Hello World!" }
MouseArea { anchors.fill: parent; onClicked: forceClose(); }
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,3 @@
BoomBlock BoomBlock.qml
Button Button.qml
Dialog Dialog.qml

View File

@ -0,0 +1,237 @@
/* This script file handles the game logic */
var maxColumn = 10;
var maxRow = 15;
var maxIndex = maxColumn*maxRow;
var board = new Array(maxIndex);
var blockSrc = "SamegameCore/BoomBlock.qml";
var scoresURL = "";
var gameDuration;
var component = Qt.createComponent(blockSrc);
//Index function used instead of a 2D array
function index(column,row) {
return column + (row * maxColumn);
}
function timeStr(msecs) {
var secs = Math.floor(msecs/1000);
var m = Math.floor(secs/60);
var ret = "" + m + "m " + (secs%60) + "s";
return ret;
}
function startNewGame()
{
//Delete blocks from previous game
for(var i = 0; i<maxIndex; i++){
if(board[i] != null)
board[i].destroy();
}
//Calculate board size
maxColumn = Math.floor(gameCanvas.width/gameCanvas.blockSize);
maxRow = Math.floor(gameCanvas.height/gameCanvas.blockSize);
maxIndex = maxRow*maxColumn;
//Close dialogs
nameInputDialog.forceClose();
dialog.forceClose();
//Initialize Board
board = new Array(maxIndex);
gameCanvas.score = 0;
for(var column=0; column<maxColumn; column++){
for(var row=0; row<maxRow; row++){
board[index(column,row)] = null;
createBlock(column,row);
}
}
gameDuration = new Date();
}
var fillFound;//Set after a floodFill call to the number of blocks found
var floodBoard;//Set to 1 if the floodFill reaches off that node
//NOTE: Be careful with vars named x,y, as the calling object's x,y are still in scope
function handleClick(x,y)
{
var column = Math.floor(x/gameCanvas.blockSize);
var row = Math.floor(y/gameCanvas.blockSize);
if(column >= maxColumn || column < 0 || row >= maxRow || row < 0)
return;
if(board[index(column, row)] == null)
return;
//If it's a valid block, remove it and all connected (does nothing if it's not connected)
floodFill(column,row, -1);
if(fillFound <= 0)
return;
gameCanvas.score += (fillFound - 1) * (fillFound - 1);
shuffleDown();
victoryCheck();
}
function floodFill(column,row,type)
{
if(board[index(column, row)] == null)
return;
var first = false;
if(type == -1){
first = true;
type = board[index(column,row)].type;
//Flood fill initialization
fillFound = 0;
floodBoard = new Array(maxIndex);
}
if(column >= maxColumn || column < 0 || row >= maxRow || row < 0)
return;
if(floodBoard[index(column, row)] == 1 || (!first && type != board[index(column,row)].type))
return;
floodBoard[index(column, row)] = 1;
floodFill(column+1,row,type);
floodFill(column-1,row,type);
floodFill(column,row+1,type);
floodFill(column,row-1,type);
if(first==true && fillFound == 0)
return;//Can't remove single blocks
board[index(column,row)].dying = true;
board[index(column,row)] = null;
fillFound += 1;
}
function shuffleDown()
{
//Fall down
for(var column=0; column<maxColumn; column++){
var fallDist = 0;
for(var row=maxRow-1; row>=0; row--){
if(board[index(column,row)] == null){
fallDist += 1;
}else{
if(fallDist > 0){
var obj = board[index(column,row)];
obj.y = (row+fallDist) * gameCanvas.blockSize;
board[index(column,row+fallDist)] = obj;
board[index(column,row)] = null;
}
}
}
}
//Fall to the left
fallDist = 0;
for(column=0; column<maxColumn; column++){
if(board[index(column, maxRow - 1)] == null){
fallDist += 1;
}else{
if(fallDist > 0){
for(row=0; row<maxRow; row++){
obj = board[index(column,row)];
if(obj == null)
continue;
obj.x = (column-fallDist) * gameCanvas.blockSize;
board[index(column-fallDist,row)] = obj;
board[index(column,row)] = null;
}
}
}
}
}
function victoryCheck()
{
//awards bonuses for no blocks left
var deservesBonus = true;
for(var column=maxColumn-1; column>=0; column--)
if(board[index(column, maxRow - 1)] != null)
deservesBonus = false;
if(deservesBonus)
gameCanvas.score += 500;
//Checks for game over
if(deservesBonus || !(floodMoveCheck(0,maxRow-1, -1))){
gameDuration = new Date() - gameDuration;
nameInputDialog.show("You won! Please enter your name: ");
nameInputDialog.initialWidth = nameInputDialog.text.width + 20;
nameInputDialog.width = nameInputDialog.initialWidth;
nameInputDialog.text.opacity = 0;//Just a spacer
}
}
//only floods up and right, to see if it can find adjacent same-typed blocks
function floodMoveCheck(column, row, type)
{
if(column >= maxColumn || column < 0 || row >= maxRow || row < 0)
return false;
if(board[index(column, row)] == null)
return false;
var myType = board[index(column, row)].type;
if(type == myType)
return true;
return floodMoveCheck(column + 1, row, myType) ||
floodMoveCheck(column, row - 1, board[index(column,row)].type);
}
function createBlock(column,row){
// Note that we don't wait for the component to become ready. This will
// only work if the block QML is a local file. Otherwise the component will
// not be ready immediately. There is a statusChanged signal on the
// component you could use if you want to wait to load remote files.
if(component.status == Component.Ready){
var dynamicObject = component.createObject(gameCanvas);
if(dynamicObject == null){
console.log("error creating block");
console.log(component.errorString());
return false;
}
dynamicObject.type = Math.floor(Math.random() * 3);
dynamicObject.x = column*gameCanvas.blockSize;
dynamicObject.y = row*gameCanvas.blockSize;
dynamicObject.width = gameCanvas.blockSize;
dynamicObject.height = gameCanvas.blockSize;
dynamicObject.spawned = true;
board[index(column,row)] = dynamicObject;
}else{
console.log("error loading block component");
console.log(component.errorString());
return false;
}
return true;
}
function saveHighScore(name) {
if(scoresURL!="")
sendHighScore(name);
//OfflineStorage
var db = openDatabaseSync("SameGameScores", "1.0", "Local SameGame High Scores",100);
var dataStr = "INSERT INTO Scores VALUES(?, ?, ?, ?)";
var data = [name, gameCanvas.score, maxColumn+"x"+maxRow ,Math.floor(gameDuration/1000)];
db.transaction(
function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(name TEXT, score NUMBER, gridSize TEXT, time NUMBER)');
tx.executeSql(dataStr, data);
//Only show results for the current grid size
var rs = tx.executeSql('SELECT * FROM Scores WHERE gridSize = "'+maxColumn+"x"+maxRow+'" ORDER BY score desc LIMIT 10');
var r = "\nHIGH SCORES for this grid size\n\n"
for(var i = 0; i < rs.rows.length; i++){
r += (i+1)+". " + rs.rows.item(i).name +' got '
+ rs.rows.item(i).score + ' points in '
+ rs.rows.item(i).time + ' seconds.\n';
}
dialog.show(r);
}
);
}
function sendHighScore(name) {
var postman = new XMLHttpRequest()
var postData = "name="+name+"&score="+gameCanvas.score
+"&gridSize="+maxColumn+"x"+maxRow +"&time="+Math.floor(gameDuration/1000);
postman.open("POST", scoresURL, true);
postman.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
postman.onreadystatechange = function() {
if (postman.readyState == postman.DONE) {
dialog.show("Your score has been uploaded.");
}
}
postman.send(postData);
}

View File

@ -0,0 +1 @@
The SameGame example can interface with a simple PHP script to store XML high score data on a remote server. We do not have a publically accessible server available for this use, but if you have access to a PHP capable webserver you can copy the files (score_data.xml, score.php, score_style.xsl) to it and alter the highscore_server variable at the top of the samegame.js file to point to it.

View File

@ -0,0 +1,2 @@
<record><score>1000000</score><name>Alan the Tester</name><gridSize>0x0</gridSize><seconds>0</seconds></record>
<record><score>6213</score><name>Alan</name><gridSize>12x17</gridSize><seconds>51</seconds></record>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head><title>SameGame High Scores</title></head>
<body>
<h2>SameGame High Scores</h2>
<table border="1">
<tr bgcolor="lightsteelblue">
<th>Name</th>
<th>Score</th>
<th>Grid Size</th>
<th>Time, s</th>
</tr>
<xsl:for-each select="records/record">
<xsl:sort select="score" data-type="number" order="descending"/>
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="score"/></td>
<td><xsl:value-of select="gridSize"/></td>
<td><xsl:value-of select="seconds"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,34 @@
<?php
$score = $_POST["score"];
echo "<html>";
echo "<head><title>SameGame High Scores</title></head><body>";
if($score > 0){#Sending in a new high score
$name = $_POST["name"];
$grid = $_POST["gridSize"];
$time = $_POST["time"];
if($name == "")
$name = "Anonymous";
//if($grid != "10x10"){
//Need a standard, so as to reject others?
//}
$file = fopen("score_data.xml", "a"); #It's XML. Happy?
$ret = fwrite($file, "<record><score>". $score . "</score><name>"
. $name . "</name><gridSize>" . $grid . "</gridSize><seconds>"
. $time . "</seconds></record>\n");
echo "Your score has been recorded. Thanks for playing!";
if($ret == False)
echo "<br/> There was an error though, so don't expect to see that score again.";
}else{#Read high score list
#Now uses XSLT to display. So just print the file. With XML cruft added.
#Note that firefox at least won't apply the XSLT on a php file. So redirecting
$file = fopen("scores.xml", "w");
$ret = fwrite($file, '<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n"
. '<?xml-stylesheet type="text/xsl" href="score_style.xsl"?>' . "\n"
. "<records>\n" . file_get_contents("score_data.xml") . "</records>\n");
if($ret == False)
echo "There was an internal error. Sorry.";
else
echo '<script type="text/javascript">window.location.replace("scores.xml")</script>';
}
echo "</body></html>";
?>

View File

@ -0,0 +1,162 @@
/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
import Qt 4.7
import "SamegameCore"
import "SamegameCore/samegame.js" as Logic
Rectangle {
id: screen
width: 490; height: 720
property bool inAnotherDemo: false //Samegame often is just plonked straight into other demos
clip:true
SystemPalette { id: activePalette }
Item {
width: parent.width
anchors { top: parent.top; left:parent.left; right: parent.right; bottom: toolBar.top }
Image {
id: background
anchors.fill: parent
source: "SamegameCore/pics/background.png"
fillMode: Image.Scale
}
Item {
id: gameCanvas
property int score: 0
property int blockSize: 40
z: 20; anchors.centerIn: parent
width: parent.width - (parent.width % blockSize);
height: parent.height - (parent.height % blockSize);
MouseArea {
anchors.fill: parent; onClicked: Logic.handleClick(mouse.x,mouse.y);
}
}
}
Dialog { id: dialog; anchors.centerIn: parent; z: 21 }
Dialog {
id: nameInputDialog
property int initialWidth: 0
anchors.centerIn: parent
z: 22;
Behavior on width {
NumberAnimation {}
enabled: nameInputDialog.initialWidth != 0
}
onOpened: nameInputText.focus = true;
onClosed: {
nameInputText.focus = false;
if (nameInputText.text != "")
Logic.saveHighScore(nameInputText.text);
}
Text {
id: dialogText
anchors { left: nameInputDialog.left; leftMargin: 20; verticalCenter: parent.verticalCenter }
text: "You won! Please enter your name: "
}
MouseArea {
anchors.fill: parent
onClicked: {
if (nameInputText.text == "")
nameInputText.openSoftwareInputPanel();
else
nameInputDialog.forceClose();
}
}
TextInput {
id: nameInputText
anchors { verticalCenter: parent.verticalCenter; left: dialogText.right }
focus: false
autoScroll: false
maximumLength: 24
onTextChanged: {
var newWidth = nameInputText.width + dialogText.width + 40;
if ( (newWidth > nameInputDialog.width && newWidth < screen.width)
|| (nameInputDialog.width > nameInputDialog.initialWidth) )
nameInputDialog.width = newWidth;
}
onAccepted: {
nameInputDialog.forceClose();
}
}
}
Rectangle {
id: toolBar
width: parent.width; height: 32
color: activePalette.window
anchors.bottom: screen.bottom
Button {
id: newGameButton
anchors { left: parent.left; leftMargin: 3; verticalCenter: parent.verticalCenter }
text: "New Game"
onClicked: Logic.startNewGame()
}
Button {
visible: !inAnotherDemo
text: "Quit"
anchors { left: newGameButton.right; leftMargin: 3; verticalCenter: parent.verticalCenter }
onClicked: Qt.quit();
}
Text {
id: score
anchors { right: parent.right; rightMargin: 3; verticalCenter: parent.verticalCenter }
text: "Score: " + gameCanvas.score
font.bold: true
color: activePalette.windowText
}
}
}

View File

@ -0,0 +1,31 @@
[Desktop Entry]
Encoding=UTF-8
Name=Same game (QML)
Name[km]= Same (QML)
Name[pt]=Jogo Same (QML)
Name[pt_BR]=Jogo Same (QML)
Name[sv]=Same game (QML)
Name[uk]=Та сама гра (QML)
Name[x-test]=xxSame game (QML)xx
Comment=The Same game QML Qt demo converted as plasmoid
Comment[km]= Same QML Qt plasmoid
Comment[pt]=O jogo Same do Qt, em QML, convertido para um plasmóide
Comment[pt_BR]=O jogo Same do Qt em QML, convertido para um plasmoide
Comment[sv]=Same game QML Qt-demonstrationen konverterad till en Plasmoid
Comment[uk]=Плазмоїд-демонстрація тієї самої гри на основі QML
Comment[x-test]=xxThe Same game QML Qt demo converted as plasmoidxx
Type=Service
ServiceTypes=Plasma/Applet
Icon=applications-games
X-Plasma-API=declarativeappletscript
X-Plasma-MainScript=qml/samegame.qml
X-KDE-PluginInfo-Author=Marco Martin
X-KDE-PluginInfo-Email=notmart@gmail.com
X-KDE-PluginInfo-Name=org.kde.samegame-qml
X-KDE-PluginInfo-Version=1.0
X-KDE-PluginInfo-Website=http://plasma.kde.org/
X-KDE-PluginInfo-Category=Examples
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true